Reputation: 61
I have the following image of a seedling tray, and I am attempting to detect the tray edges.
When I attempt to run a Canny edge detection - after applying a Gaussian blur - this is the result that is provided:
Running a probabilistic Hough transform results in a jumbled mess like so:
Are there any opencv functions that should be used instead due to the detail and level of objects present in the image? Should I use a different program entirely? Here is an example of what I would hope the output would achieve:
Upvotes: 0
Views: 356
Reputation: 173
import cv2 as cv
import numpy as np
import math
def removebg(x,s):
# return x - cv.GaussianBlur(x,(s,s),0)
bi = cv.medianBlur(x,s).astype(np.float32)
return x - (bi.astype(np.float32) - np.mean(bi))
def threshold_and_hough_lines(x,thresh):
# x = (x > 10) *255
x = x.astype(np.uint8)
return cv.HoughLines(x,1,np.pi/360,thresh)
def outliers(x,factor=1):
l,median,u = np.quantile(x,[.25,.5,.75])
iqd = u-l
_,thresh = cv.threshold(x,median+factor*iqd,np.max(x),cv.THRESH_BINARY)
return thresh
img = cv.imread("/data/stuff/seeds.jpeg")
print(img.shape)
draw_len=max(img.shape)*2
img_rembg = removebg(img,201)
cv.imwrite('img_rembg.jpg',img_rembg)
gray = np.mean(img_rembg,axis=2)
cv.imwrite('gray.jpg',gray)
thresh = outliers(gray)
cv.imwrite('thresh.jpg',thresh)
structure_element = np.ones((35,1))
structure_element = structure_element.astype(np.uint8)
iters=1
vlines = cv.morphologyEx(thresh, cv.MORPH_OPEN, structure_element,iterations=iters)
hlines = cv.morphologyEx(thresh, cv.MORPH_OPEN, structure_element.T,iterations=iters)
cv.imwrite('vlines.jpg',vlines)
cv.imwrite('hlines.jpg',hlines)
hough_thresh=int(math.sqrt(img.shape[0]*img.shape[1])*.3)
print(hough_thresh)
linesh = threshold_and_hough_lines(hlines,hough_thresh)
linesv = threshold_and_hough_lines(vlines,hough_thresh)
for line in (*linesh,*linesv):
rho,theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + draw_len*(-b))
y1 = int(y0 + draw_len*(a))
x2 = int(x0 - draw_len*(-b))
y2 = int(y0 - draw_len*(a))
cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv.imwrite('combined.jpg',img)
I updated my method with some pre-processing to flatten the image ("removebg") as well as morphological operations (open and close) with structual elements matching a vertical bar and horizontal bar separately to enhance the planter edges after thresholding. Most of the parameters can be tuned for different size objects and images, which was the main problem going from the small resolution photo to full resolution. The main parameter of HoughLines is the detection threshold, which I put together a rough calculation based on the size of the image that seems to work well. This code seems to work with both small and large versions of the example image.
The first thing I would mess with to get those missing horizontal lines is the multiplyer on hough_thresh (set to .3 in this post). Lower = more lines detected.
I explored some convolution based methods and I recommend taking a look at them. Trying to match the shape of each planter or maybe corners may be better in the long run if you consistently have images with obscured lines.
Upvotes: 2