15

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

1 Answer 1

42

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(); } 
Sign up to request clarification or add additional context in comments.

8 Comments

Thank you very much, i will try this today :D Oh, i am a fan of your blog :)
Do you have any version for C++? :P
Hi, all the functions are standard functions from OpenCV. So if you check the opencv docs, you can find corresponding C++ functions for every python function I used. Please try it yourself, and if you find any difficulty, comment me. I will try to help...
+1 - Thank you, It is good to know you benefit from my blog. Keep visiting, and share it if you like.
Sorry for so long time. I did it, thanks :) Check my latest project: youtube.com/watch?v=zXHXusO8eGw
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.