Home > Software engineering >  Measuring the width of a hot steel plate with OpenCV
Measuring the width of a hot steel plate with OpenCV

Time:09-06

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?

Steel Plate

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.

enter image description here

Lowpassed:

enter image description here

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()

plots

  • Related