There is a noisy and blurry image that contains an edge that must be detected. The edge is clearly visible to the human eye, but I'm having trouble letting OpenCV detect it.
The image in question:
You need to adjust the contrast and brightness to see it. I only wanted to post the original image.
The edge that is to be detected is the thick black one that runs horizontally, after the ROI is applied. Here is what I have tried so far:
import numpy as np
from PIL import Image
import cv2
file = "input3.tif"
im = Image.open(file)
imarray = np.array(im)
roi = imarray[230:310, 460:660]
img8 = (roi/2).astype('uint8')
cv2.imshow('img8', img8)
blur = cv2.bilateralFilter(img8,9,5,150)
cv2.imshow('blur', blur)
kernel = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]])
sharpened = cv2.filter2D(blur, -1, kernel)
cv2.imshow('sharpened', sharpened)
edges = cv2.Canny(sharpened,150, 250, apertureSize=3)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 20, minLineLength=100, maxLineGap=8)
for line in lines:
for x1, y1, x2, y2 in line:
cv2.line(img8, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow('out', img8)
With the undesired
.
What improvements can be made so that only the horizontal edge is detected?
as others suggested, it would be much easier to use cv2.equalizeHist
to correct the image, the following code worked well for me:
im = cv2.cvtColor(cv2.imread("unsharp.jpg"),cv2.COLOR_BGR2RGB) # read as rgb for easy plotting
gray = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY) # convert to gray
roi = gray[230:310, 460:660].copy() # copy to roi
imHistEqual = cv2.equalizeHist(roi) # equalize
edges = cv2.Canny(imHistEqual,150, 250, apertureSize=3) # detect edges
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 20, minLineLength=50, maxLineGap=8) # detect lines, corrected minLineLength to 50
roiContoured = roi.copy() # copy for contouring
# for loop to draw lines
for line in lines:
for x1, y1, x2, y2 in line:
cv2.line(roiContoured, (x1, y1), (x2, y2), (255, 255, 255), 3)
The results are like this:
Also, the minLineLength
of 100 which you set before was a bit too much, I lowered it to 50 and the horizontal line was detected.
Some info about the plots, all are plotted like this:
fig, ax = plt.subplots(nrows = 3, ncols = 1, sharex = True, sharey = True)
ax[0].imshow(roi, cmap = "gray", vmin = 0, vmax = 255)
ax[1].imshow(imHistEqual, cmap = "gray", vmin = 0, vmax = 255)
ax[2].imshow(roiContoured, cmap = "gray", vmin = 0, vmax = 255)
ax[0].axis("off")
ax[1].axis("off")
ax[2].axis("off")
ax[0].set_title("roi")
ax[1].set_title("after cv2.equalizeHist")
ax[2].set_title("after line detection")
plt.show()
plt.savefig("LineDetection.png", dpi = 330)