Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect Lines Opencv in object

Tags:

opencv

I have the image below. I want to detect the line that divides this object in two pieces. Which is the best way? I've tried with the Hough transform but sometimes the object is not big enough for it to detect. Any ideias?

Thanks!

enter image description here

like image 630
Luis Carlos Avatar asked Jan 06 '13 16:01

Luis Carlos


People also ask

What algorithm is used to detect lines in OpenCV?

The Hough Transform is a method that is used in image processing to detect any shape, if that shape can be represented in mathematical form. It can detect the shape even if it is broken or distorted a little bit.

How do I find the lines of an image in Python?

Use the HoughLinesP() Function of OpenCV to Detect Lines in an Image in Python. The HoughLinesP() function uses probabilistic Hough line transform to detect lines. We have to read the given image using the imread() function, convert it into grayscale, and then find its edges using Canny() .

How is a line detected in image processing?

In image processing, line detection is an algorithm that takes a collection of n edge points and finds all the lines on which these edge points lie. The most popular line detectors are the Hough transform and convolution-based techniques.

What algorithm is used to detect lines?

Thus, the Hough Transform algorithm detects lines by finding the (ρ, θ) pairs that have a number of intersections larger than a certain threshold.


1 Answers

Normally, Hough Transform is used for line detection.

But if it doesn't work for you, fitting line is also a good alternative.

Check OpenCV fitline function for more details and parameters.

Since you have already tried hough lines, I will demonstrate fitting line here, using OpenCV-Python :

# Load image, convert to grayscale, threshold and find contours
img = cv2.imread('lail.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hier = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]

# then apply fitline() function
[vx,vy,x,y] = cv2.fitLine(cnt,cv2.cv.CV_DIST_L2,0,0.01,0.01)

# Now find two extreme points on the line to draw line
lefty = int((-x*vy/vx) + y)
righty = int(((gray.shape[1]-x)*vy/vx)+y)

#Finally draw the line
cv2.line(img,(gray.shape[1]-1,righty),(0,lefty),255,2)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Below is the result I got :

enter image description here

enter image description here

EDIT :

If you want to find the line to divide the object into two pieces, first find the fitting line, then find the line normal to it.

For that, add below piece of code under cv2.fitLine() function :

nx,ny = 1,-vx/vy
mag = np.sqrt((1+ny**2))
vx,vy = nx/mag,ny/mag

And below are the results I got :

enter image description here

enter image description here

Hope it helps !!!

UPDATE :

Below is the C++ code for Python code of first case as you requested. The code works fine for me. Output is same as given above :

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv/cv.h>

using namespace std;
using namespace cv;

int main()
{
    cv::Mat img, gray,thresh;
    vector<vector<Point>> contours;
    Vec4f lines;

    img = cv::imread("line.png");
    cv::cvtColor(img,gray,cv::COLOR_BGR2GRAY);
    cv::threshold(gray,thresh,127,255,cv::THRESH_BINARY);
    cv::findContours(thresh,contours,cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE);
    cv::fitLine(Mat(contours[0]),lines,2,0,0.01,0.01);

    //lefty = int((-x*vy/vx) + y)
    //righty = int(((gray.shape[1]-x)*vy/vx)+y)
    int lefty = (-lines[2]*lines[1]/lines[0])+lines[3];
    int righty = ((gray.cols-lines[2])*lines[1]/lines[0])+lines[3];

    cv::line(img,Point(gray.cols-1,righty),Point(0,lefty),Scalar(255,0,0),2);

    cv::imshow("img",img);
    cv::waitKey(0);
    cv::destroyAllWindows();
}
like image 129
Abid Rahman K Avatar answered Oct 05 '22 17:10

Abid Rahman K