Original Post
I have a batch of similar images which I need to analyze.
After
- thresholding
- hole filling using
skimage.morphology.reconstruction
(example of usage here) - image closing
I get something like this image:
I'm interested in the edges of shape, specifically the steepness of the slope along vertical lines in the original grayscale image. I thought I could use Canny to get the contours which indeed gave me:
My questions:
- How would I go about separating the approximately vertical and horizontal edges? The have very different meaning for me, as I'm not at all interested in what happens between adjacent horizontal lines (I would rather just cut those parts from the image), and I'm interested in what happens around vertical lines (white surrounding in the BW image).
- I'm would assume my lines should be straight (there could be a slope, but the noise is too high). How would I smoothen the contour lines?
- Eventually I wish to go back to the gray scale image and look at the pixel statistics in the vicinity of vertical lines. How can extract the location info of lines from the edges found by Canny?
My code:
im_th= cv2.inRange(img, 0, 500, cv2.THRESH_BINARY)
seed = np.copy(im_th)
seed[1:-1, 1:-1] = im_th.max()
mask = im_th
filled = reconstruction(seed, mask, method='erosion').astype(np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(4,4))
closed = cv2.morphologyEx(filled,cv2.MORPH_CLOSE, kernel=kernel)
edges = cv2.Canny(cv2.medianBlur(closed, 5), 50, 150)
Edit
Per suggestions of Christoph Rackwitz and mimocha, I attempted using findContours
and HoughLinesP
. Both results look promising, but require further work to be of use.
findContours approach
Code:
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour_img = cv2.drawContours(cv2.cvtColor(closed, cv2.COLOR_GRAY2BGR), contours, -1, (255,0,0), 3)
Resulting image (overlay over the closed image):
The contours are found nicely, I still 151 contour lines. I would want to smoothen the result and get less lines.
HoughLinesP approach
Code:
threshold = 15
min_line_length = 30
max_line_gap = 200
line_image = np.copy(cv2.cvtColor(closed, cv2.COLOR_GRAY2BGR)) * 0
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold, None, min_line_length, max_line_gap)
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(line_image,(x1,y1),(x2,y2),(255,0,0),5)
lines_edges = cv2.addWeighted(cv2.cvtColor(closed, cv2.COLOR_GRAY2BGR), 0.2, line_image, 1, 0)
Resulting image:
HoughLinesP indeed guarantees straight lines, and it find the lines nicely, but I still have some lines which are too "thick" (you can see in the image some thick lines which are actually parallel lines). Thus I need some method for refining this results.
Summary so far:
- Both the contours approach and the Hough transform approach have gain.
- Hough transform may have an advantage as it returns straight lines, and also allows to separate horizontal in vertical lines as shown here.
- I still need a method to merge/cluster lines.