user3065529
user3065529

Reputation: 35

Find main line (and its angle) in an image

I want to identify the main line in an image, and its angle (the lines running across the centre of the image). I start with an image (see link, https://i.sstatic.net/JfoHC.png) I have pre-processed using ImageJ (reduce noise, shadows and find edges). Any help would be much appreciated!

My code thus far,

import cv2 as cv
import numpy as np
import matplotlib as plt
import matplotlib.pyplot as pltt
from scipy.stats import linregress

# Import image and convert to grayscale
im = cv.imread(https://i.sstatic.net/JfoHC.png)
pltt.imshow(im)
pltt.show()
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)

# Convert grayscale image into binary mask
ret, thresh = cv.threshold(imgray, 200, 255, cv.THRESH_OTSU)

# Find contours in binary mask and plot binary mask
_, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
window_name = 'Thresh'
pltt.imshow(thresh)
pltt.show()
cnt = contours[0]
M = cv.moments(thresh)
rows,cols = im.shape[:2]

# Fit line to identified contours in image and plot the results
[vx,vy,x,y] = cv.fitLine(cnt, cv.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
line = cv.line(im,(cols-1,righty),(0,lefty),(0,255,0),2)
window_name = 'Image'
color = (0, 255, 0)
thickness = 9
imagee = cv.line(im, (cols-1,righty),(0,lefty),(0,255,0),2)
cv.imshow(window_name, imagee)
pltt.imshow(imagee)
pltt.show()

Result from image pre-processing and edge detection using ImageJ Result from binary threshold using Python 3.7 (OpenCV) Result from my code above: Line fitted to contours

Upvotes: 0

Views: 892

Answers (2)

Frank Musterman
Frank Musterman

Reputation: 657

cnt 0 is probably not the right one to look at, as mentioned in the comments.

cv.drawContours(im, contours, 0, (0,250,0), 3) is useful to see that.

check out - https://docs.opencv.org/3.4/d4/d73/tutorial_py_contours_begin.html

also if you draw the "right" - biggest contour you would still probably get a weird fit - but it's no longer very far from the truth:

MAX = 0 
for i in range(len(contours)):
    if len(contours[i]) > MAX:
        MAX = len(contours[i])
        MAX_ind = i

cv.drawContours(im, contours, MAX_ind, (100,255,0), 3)
pltt.imshow(im)

result

Upvotes: 1

Ziri
Ziri

Reputation: 736

Use Opencv line segment detector to be able to measure it's Size. take a look at cv2.createLineSegmentDetector()

Upvotes: -1

Related Questions