I want to measure the width along the green line in the image, I applied filters like canny via OpenCV but I guess the filter didn't work (can't show the edges) because of the very high temperature. My idea is to draw 2 vertical lines and measure by drawing a line between them (I want to draw the vertical edges of the object in the picture, so). Is there any method that can work for this?
CodePudding user response:
The red component binarizes wonderfully, so it won't be a big deal to find the sides.
For more accuracy, you can lowpass filter vertically to reduce noise. You can also do subpixel interpolation by using a linear model that straddles the edge. But I am not sure that this luxury is required for your case.
Lowpassed:
CodePudding user response:
- take a row of pixels
- take red channel only (others contain no information)
- lowpass it a bit to suppress noise
- gradient
- maximum and minimum are rising and falling edge
From that, falling - rising
, you directly have the width in pixels of your workpiece, at that scanline through the image.
You could also, and maybe should, use a global threshold instead of going for edges. In this picture, a threshold of 0.4 looks good. You could use Otsu's method to determine that.
im = cv.imread("UEj1P.png")
# try threshold using Otsu
row_u8 = im[550, :, 2] # red channel
(otsulevel, thresh) = cv.threshold(row_u8, 0, 255, cv.THRESH_BINARY cv.THRESH_OTSU)
row = im[500:550, :, 2].mean(axis=0) / 255
lowpassed = scipy.ndimage.gaussian_filter1d(row, sigma=2.0)
gradient = np.gradient(lowpassed)
rising = np.argmax(gradient)
falling = np.argmin(gradient)
# two plots in the figure
fig, ax = plt.subplots(2, 1, figsize=(15, 10))
# first plot: row
ax[0].plot(row)
ax[0].plot(lowpassed)
# otsu threshold line
ax[0].axhline(otsulevel/255, color="blue")
# second plot: gradient
ax[1].plot(gradient)
# draw some vertical lines at rising and falling edge
ax[0].axvline(x=rising, color="red")
ax[0].axvline(x=falling, color="red")
ax[1].axvline(x=rising, color="red")
ax[1].axvline(x=falling, color="red")
plt.show()