'How to detect and separate vertical and horizontal line and add a circle in the middle of a line from a video opencv

The problem I'm experiencing is that when the horizontal line doesn't form a 180-degree straight line, the hough lines will be fragmented and untidy. Please help so that I can detect a horizontal line using a certain angle or if it has entered a certain angle it will be detected and not cut off in the middle.

This is when the line is straight

This is when the line is not straight

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
// using namespace cv;
int hueminFIELD = 32, huemaxFIELD = 86, satminFIELD= 81, satmaxFIELD = 255, valminFIELD = 0, valmaxFIELD = 255;
int hueminLINE = 0, huemaxLINE = 179, satminLINE= 0, satmaxLINE = 255, valminLINE = 218, valmaxLINE = 255;
cv::Mat hsv, mask;



void getCountours(cv::Mat tebel, cv::Mat gambar){
    vector<vector<cv::Point>> kontur;
    vector<cv::Vec4i> hierarki;
    findContours(tebel,kontur,hierarki,cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
    vector<cv::Rect> bataskotak(kontur.size());
    vector<vector<cv::Point>> hull(kontur.size());
    for (int i = 0; i < kontur.size(); i++)
    {
        int area = cv::contourArea(kontur[i]);// vector<vector<Point>> konpoli(kontur.size());[i]);
        convexHull(cv::Mat(kontur[i]),hull[i]);
        drawContours(gambar, hull, i, cv::Scalar(255,0,255),-1); 
        float batas = cv::arcLength(kontur[i],true);
        bataskotak[i]=cv::boundingRect(kontur[i]);
        // cv::rectangle(gambar, bataskotak[i].tl(), bataskotak[i].br(), cv::Scalar(255,0,255), -1);
        cv::circle(gambar, cv::Point((bataskotak[i].tl()+bataskotak[i].br())/2), 6, cv::Scalar(255,255,255), cv::FILLED);
        
    }
}



int main(){

    cv::VideoCapture vid("lapa.mp4");
    //trackbar buat nyari warna putih
    cv::namedWindow("Trackbar", cv::WINDOW_AUTOSIZE);
    cv::createTrackbar("Hue min", "Trackbar", &hueminLINE, 179);
    cv::createTrackbar("Hue max", "Trackbar", &huemaxLINE, 179);
    cv::createTrackbar("Saturation min", "Trackbar", &satminLINE, 255);
    cv::createTrackbar("Saturation Max", "Trackbar", &satmaxLINE, 255);
    cv::createTrackbar("Value min", "Trackbar", &valminLINE, 255);
    cv::createTrackbar("Value max", "Trackbar", &valmaxLINE, 255);
    
    while(1){
        cv::Mat video;
        vid.read(video);
        cv::resize(video,video,cv::Size(640,480));

        //Segmentasi warna lapangan
        //cv::GaussianBlur(video,video,cv::Size(3,3),5,2);
        cv::cvtColor(video, hsv, cv::COLOR_BGR2HSV);
        cv::Scalar lower(hueminFIELD, satminFIELD, valminFIELD);
        cv::Scalar upper(huemaxFIELD, satmaxFIELD, valmaxFIELD);
        cv::inRange(hsv, lower,upper, mask); 
        // cv::cvtColor(mask,mask,cv::COLOR_GRAY2BGR);
        // cv::Mat hasil; //untuk menyimpan hasil video.

        //Bagian kontur
        vector<vector<cv::Point>> kontur;
        vector<cv::Vec4i> hierarki;
        findContours(mask, kontur, hierarki, cv::RETR_TREE,cv::CHAIN_APPROX_NONE);
        vector<cv::Point> for_convex;
        cv::Mat drawing = cv::Mat::zeros(mask.size(), CV_8UC3);

        for (int i = 0; i < kontur.size(); i++)
        {
            for_convex.insert(for_convex.end(), kontur[i].begin(), kontur[i].end());
        }
        vector<cv::Point> convexed;
        convexHull(for_convex,convexed);
        vector<vector<cv::Point>> convexbener;
        convexbener.push_back(convexed);
        
        drawContours(drawing,convexbener,0,cv::Scalar(255,255,255),-1);
        
        

        //Bagian segmentasi garis putih
        cv::Mat lapangan;
        cv::bitwise_and(video,drawing,lapangan);
        // cv::imshow("lapangan",lapangan);
        // cv::imshow("drawing",drawing);
        cv::Mat lapanganhsv;
        cv::cvtColor(lapangan, lapanganhsv, cv::COLOR_BGR2HSV);
        cv::Scalar lowerLINE(hueminLINE, satminLINE, valminLINE);
        cv::Scalar upperLINE(huemaxLINE, satmaxLINE, valmaxLINE);
        cv::Mat maskline;
        cv::inRange(lapanganhsv, lowerLINE,upperLINE, maskline);

        cv::Mat strukturgaris = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3));
        cv::dilate(maskline,maskline,strukturgaris);
        //cari kontur garis kemudian convexhull
        // vector<vector<cv::Point>> kontur_line;
        // vector<cv::Vec4i> hierarki_line;
        // findContours(maskline, kontur_line, hierarki_line, cv::RETR_TREE,cv::CHAIN_APPROX_NONE);
        // cv::Mat drawing_line = cv::Mat::zeros(maskline.size(), CV_8UC3);

        // for (int i = 0; i < kontur_line.size(); i++)
        // {
        //     int area_line = cv::contourArea(kontur_line[i]);
        //     drawContours(drawing_line,kontur_line,0,cv::Scalar(255,0,255),-1);
        // }
        
        
        
        // cv::cvtColor(maskline,maskline,cv::COLOR_GRAY2BGR);
        cv::imshow("maskline",maskline);
        // cv::imshow("kontur",drawing_line);
        cv::Mat hasilakhir;
        // cv::bitwise_and(video, drawing_line, hasilakhir);
        // cv::imshow("hasilconvexline",hasilakhir);
        
        //mulai deteksi garis
        

        //horizontal
        // cv::Mat cloning,horizontalStructure;
        // cloning = maskline.clone();
        // int horizontalSize = maskline.cols/7.5;

        // horizontalStructure = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(horizontalSize,1));

        // erode(maskline, maskline, horizontalStructure, cv::Point(-1, -1));
        // dilate(maskline, maskline, horizontalStructure, cv::Point(-1, -1));

        // std::vector<std::vector<cv::Point>> contour_garis;
        // std::vector<cv::Point > contour_line_point;
        // findContours(maskline,contour_garis,hierarki,cv::RETR_TREE,cv::CHAIN_APPROX_NONE);
        // for(size_t i = 0; i < contour_garis.size(); i++){
        // // std::cout<<"cv::contourArea(contours_lines[i]) : "<<cv::contourArea(contours_lines[i])<<std::endl;
        //     if(cv::contourArea(contour_garis[i]) > 150){
        //     contour_line_point.insert(contour_line_point.end(), contour_garis[i].begin(), contour_garis[i].end());
        // }
        // cv::cvtColor(horizontal,horizontal,cv::COLOR_GRAY2BGR);
        
        // cv::cvtColor(horizontal,horizontal,cv::COLOR_GRAY2BGR);
        // cv::imshow("maskline",lapangan);
        // cv::Mat hasilakhir;
        //cv::bitwise_and(video,maskline,hasilakhir);
        //cv::imshow("videoawaL",hasilakhir);

        //SKELETON
        cv::Mat skel(maskline.size(), CV_8UC1, cv::Scalar(0));
        cv::Mat temp(maskline.size(), CV_8UC1);
        cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3, 3));
        bool done;
        do
        {
        cv::morphologyEx(maskline, temp, cv::MORPH_OPEN, element);
        cv::bitwise_not(temp, temp);
        cv::bitwise_and(maskline, temp, temp);
        cv::bitwise_or(skel, temp, skel);
        cv::erode(maskline, maskline, element);
        
        double max;
        cv::minMaxLoc(maskline, 0, &max);
        done = (max == 0);
    } while (!done);

    //Hough Line dari skeleton
    vector<cv::Vec4i> lines;
    HoughLinesP(skel,lines,2, CV_PI/180,80,0,200);

    cv::Mat maskbgr;
    cvtColor(maskline, maskline, cv::COLOR_GRAY2BGR);

    // gambar hough line
    for (size_t i = 0; i < lines.size(); i++)
    {
        cv::Vec4i l = lines[i];
        line(maskline, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0),1,cv::LINE_AA);
    }

    //HORIZONTAL
        cv::Mat bw;
        cv::adaptiveThreshold(skel, bw, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 15, -2);
        
        cv::Mat horizontal = bw.clone();
        int horizontal_size = horizontal.cols / 40;
        cv::Mat horizontalStructure = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(horizontal_size, 1));
        cv::erode(horizontal, horizontal, horizontalStructure);
        cv::dilate(horizontal, horizontal, horizontalStructure,cv::Point(-1,-1),10);

    
        // getCountours(horizontal,video);
        
    // // Hough line prob
    vector<cv::Vec4i> horiz_lines;
    HoughLinesP(horizontal,lines,1, CV_PI/180,80,0,300);

    // Mat maskbgr;
    cvtColor(horizontal, horizontal, cv::COLOR_GRAY2BGR);

    // // gambar hough line
    for (size_t i = 0; i < lines.size(); i++)
    {
        cv::Vec4i l = lines[i];
        line(video, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0),1,cv::LINE_AA);
    }
    cv::Mat eroded;
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(5,5));
    cv::erode(horizontal,eroded,kernel,cv::Point(-1,-1), 3);

    
        cv::imshow("horizontal", horizontal);
        cv::imshow("video", video);
        //VERTIKAL
        // cv::cvtColor(horizontal,horizontal,cv::COLOR_BGR2GRAY);
        // cv::Mat blur_line;
        // cv::GaussianBlur(horizontal, blur_line,cv::Size(5,5),0); 
        // cv::Mat edges;
        // cv::Canny(blur_line,edges,50,150);
        // cv::imshow("edges",edges);
        cv::waitKey(100);
        
    }
    return 0;
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source