Search code examples
pythonopencvimage-processingimage-optimization

Image processing operations and methods for geometry extraction


I already asked this question and I solved one task of my original question. However, I am still struggling with obtaining a decent pre-processing image.

In general, I am trying to approximate different shapes of a weld bead geometry cross section in additive manufacturing with a graph or ideally (but not necessarily) a function. The regions are the outer shape as well as the individual layers. (see following images) Prior to that I must pre-process the image so that I can apply my algorithm which predicts the distance between the layers as well as the width of each layer.

Original RGB Image

How the approximation should look like

So far, I applied some pre-processing methods to extract the relevant pixels which represent the geometry of a weld bead which are shown as white pixels (see third image) and which are relevant for predicting the height and shape of each weld bead layer. I derived this image with canny edge detection and thresholding methods in different colour spaces as (including greyscale) and multiple morphological operations such as closing erosion and dilation prior to that.

As you can see, my results weren't good, I either loose too much information of the "relevant" transition region or get too much noise between the weld bead layers. The "noisy" areas are the transition areas between individual layers of metal and only show up in this way, so in general there is not a "better" or "sharper" transition in thus less "noise". Pictures 3 and 4 are an example of some of the image pre-processing methods I used.

In my mind a somehow densitiy-based (e. g. for a binary image regarding the white pixels) denoising would maybe be helpful to eliminate the noise between the layers so in the region where it is not desired while preserving the pixels in the relevant transition region.

Image preprocessing using global thresholding

Pre-processed Image (to be approximated)

If anybody who's experienced in image processing or image vision can give me some advice, I would highly appreciate that!

If you need to take a look at my code, just let me know. Thank you! :)


Solution

  • Here is one idea in Python/OpenCV.

    Scale the image down by say 25% to emphasize the dark bands. Then average along each column. Then get the profile of the averaged data. You can then measure more accurately on the profile for the spacing and then multiply by 4 to compensate for the 25% reduction.

    Input:

    enter image description here

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    # Read image
    img = cv2.imread('weld_bead.jpg')
    
    # convert to gray
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # scale image by 25%
    img_small = cv2.resize(gray, (0,0), fx=0.25, fy=0.25, interpolation=cv2.INTER_AREA)
    hh, ww = img_small.shape[:2]
    
    # compute mean of each column
    mean = np.mean(img_small, axis=0)
    
    # scale the mean up vertically for viewing
    mean_stretch = cv2.resize(mean, (hh,ww), fx=0, fy=0, interpolation=cv2.INTER_AREA).transpose()
    
    # show results
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    plt.imshow(img_small, cmap='gray')
    ax = plt.axes()        
    ax.xaxis.grid(color='black')
    plt.title("Weld Bead Scaled By 25%")
    plt.savefig('weld_bead_small.png')
    plt.show()
    
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    plt.imshow(mean_stretch, cmap='gray')
    ax = plt.axes()        
    ax.xaxis.grid(color='black')
    plt.title("Weld Bead Average Stretched In Y")
    plt.savefig('weld_bead_ave_stretch.png')
    plt.show()
    
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    plt.plot(mean,color = 'black')
    major_ticks = np.arange(0, ww, 50)
    minor_ticks = np.arange(0, ww, 10)
    ax.set_xticks(major_ticks)
    ax.set_xticks(minor_ticks, minor=True)
    ax.grid(which='minor', alpha=0.5)
    ax.grid(which='major', alpha=1)
    plt.grid(color='gray')
    plt.title("Weld Bead Profile")
    plt.savefig('weld_bead_plot.png')
    plt.show()
    

    enter image description here

    enter image description here

    enter image description here