Combine the area and edge brightness to improve the ring detection accuracy

Posted by Jabop on Fri, 28 Jan 2022 19:03:42 +0100

Introduction: This paper discusses how to combine the contour area method with the edge brightness curve modeling method in the process of detecting the diameter of the ring in the metal template to see whether the accuracy of the ring can be improved. From the test results, it does not show the advantages of the two combination methods.

Key words: ring detection, boundary area, center

 

§ 01 ring detection

1.1 problem background

  in Using edge gray change modeling to improve the accuracy of ring diameter This paper discusses the method to increase the measurement accuracy by modeling the brightness change of the ring boundary in the picture of bacteriostatic ring metal template. Final certificate:

  • This method can improve the circle radius obtained by HoughCircles transform;
  • But compared to Measuring circular radius by circular contour area For the above method, the area measurement accuracy has not been achieved by using the transformation brightness change modeling.

   therefore, the next question remains: can these two methods be combined to finally improve the measurement accuracy?

1.1.1 method combination

  there are two ways to combine edge brightness modeling and contour area statistics:
  1. Using the parameters in the edge brightness modeling to provide the binarization threshold in the contour area;
  2. The center point of contour area is used to provide the center point for edge brightness modeling;

   the following is an experimental study to verify whether the combination of the above two methods is effective.

1.2 contour area method

  the processing program comes from Measuring circular radius by circular contour area The final handler of the blog post. The processed picture data is 100 pieces of data obtained by the diagonal translation of the template above the scanning.

1.2.1 contour area calculation circular radius

   the following is the change of the circular radius calculated by the contour area with the diagonal translation of the metal template on the scanner surface. It can be seen that the radius data of both large and small circles fluctuate periodically with translation, and the fluctuation phases of the two circles are just complementary, showing a phase difference of about 180 °.

▲ figure 1.2.1 data of circular radius obtained by contour area

1.2.2 take the average radius of large circle and small circle

   according to the above fluctuations, divide two large circles and two small circles into two groups, average them, and check the change of values after average.

   the following figure shows the change of measurement curve after averaging the large circle and the small circle respectively:

  • Indeed, the original volatility has been greatly reduced;
  • But the fluctuation has not completely disappeared;

▲ the measurement results corresponding to the average values of two large circles and two small circles

  the data range after average is shown below:

max(r1a)-min(r1a): 0.409755637718888
max(r2a)-min(r2a): 0.742439612301439

   the following is the variance and range corresponding to the original four circle radii. It can be seen that after the average value, these ranges are also relatively reduced.

std(rdim1): 0.10686994419992152
std(rdim2): 0.12228622717628217
std(rdim3): 0.24442592829855
std(rdim4): 0.2037604935717777
max(rdim1)-min(rdim1): 0.49655149847501434
max(rdim2)-min(rdim2): 0.6161167744770495
max(rdim3)-min(rdim3): 0.9954571335234874
max(rdim4)-min(rdim4): 0.8185206978833861

  however, the reason for the small decrease is that there is still a trend of large data increase on the basis of the original data fluctuation. This change has become a major contribution to the poor data.

 

§ 02 method fusion

2.1 the first fusion scheme

   the first fusion scheme is to use circular edge gray modeling to estimate the threshold of image segmentation through modeling parameters.

2.1.1 code change

#------------------------------------------------------------

cealldiag = '/home/aistudio/work/Scanner/cealldiag.npz'
cealldata = load(cealldiag, allow_pickle=True)
ceall = cealldata['ceall']

#------------------------------------------------------------

def sigmoidx(x, a,b,c,d):
    return a/(1+exp(-(x-c)*d)) + b

#------------------------------------------------------------
block_side = 140
def img2block(img, circles):
    block = []
    for c in circles:
        left = int(c[0] - block_side)
        right = left + block_side*2
        top = int(c[1] - block_side)
        bottom = top + block_side*2

        block.append(img[top:bottom, left:right, :])

    return block

#------------------------------------------------------------
rdim1 = []
rdim2 = []
rdim3 = []
rdim4 = []

threshold = 100
threshdim = []

for id,f in tqdm(enumerate(allfile)):
    img = cv2.imread(f)
    cc = alldim[id]
    ce = ceall[id]

#    if id >= 41: break

    #--------------------------------------------------------
'''
    for c in cc:
        printt(c:)
        cv2.circle(img, (c[0], c[1]), int(c[2]), (0,0,255), 10)

    plt.figure(figsize=(10,10))
    plt.imshow(img[:,:,::-1])

    break
'''
    #--------------------------------------------------------

    block = img2block(img, cc)

    #--------------------------------------------------------
'''
    plt.figure(figsize=(10,10))
    plt.subplot(2,2,1)
    plt.imshow(block[0])
    plt.subplot(2,2,2)
    plt.imshow(block[1])
    plt.subplot(2,2,3)
    plt.imshow(block[2])
    plt.subplot(2,2,4)
    plt.imshow(block[3])

    plt.savefig('/home/aistudio/stdout.jpg')
    break
'''
    #--------------------------------------------------------

#    plt.figure(figsize=(10,10))

    ratioDim = []
    x = linspace(0, 100, 100, endpoint=False)
    for iidd,b in enumerate(block):

        y = ce[iidd]
        param = [140, 20, 50, 0.2]
        param, conv=curve_fit(sigmoidx, x,  y, p0=param)

        bgray = cv2.cvtColor(b, cv2.COLOR_BGR2GRAY)
#        threshold = mean(bgray.flatten())
        threshold = (param[0]/2+param[1])
        threshdim.append(threshold)

        ret,thresh = cv2.threshold(bgray, threshold, 255, 0)
        contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
        cv2.drawContours(b, contours, -1, (0, 0, 255), 3)

        areaDim = []
        for id,c in enumerate(contours):
            areaDim.append(cv2.contourArea(c))

        asorted = sorted(areaDim)
        a = asorted[-2]
        r = sqrt(a/pi)
        ratioDim.append(r)

#        plt.subplot(2,2,iidd+1)
#        plt.hist(bgray.flatten(), bins=20)
#        plt.imshow(b[:,:,::-1])

#    printt(ratioDim:)
    if len(ratioDim) != 4:
        printt(ratioDim:)
        break

    rdim1.append(ratioDim[0])
    rdim2.append(ratioDim[1])
    rdim3.append(ratioDim[2])
    rdim4.append(ratioDim[3])

#    plt.savefig('/home/aistudio/stdout.jpg')
#    plt.show()

#    break

2.1.2 treatment results

▲ figure 2.1.1 processing results

max(r1a)-min(r1a): 0.42009826663701233
max(r2a)-min(r2a): 0.7635241870300433
std(rdim1): 0.10759563831366077
std(rdim2): 0.12086249841122422
std(rdim3): 0.24667243762087157
std(rdim4): 0.21136071101720186
max(rdim1)-min(rdim1): 0.5210168958673478
max(rdim2)-min(rdim2): 0.619309102259777
max(rdim3)-min(rdim3): 0.95698803317228
max(rdim4)-min(rdim4): 0.8067502496432724

  whether from the processing data curve or from the final statistics, this combination has not improved. The improvement effect is very weak.

2.2 the second scheme

   the second scheme is to use the center of the boundary to correct the center point in the modeling of edge brightness curve.

2.2.1 find the boundary Center

  in the blog OpenCV center of contour Using CV2 The moments function calculates the method in contoursde.

M = cv2.moments(c)
m00 = M['m00']

if m00 > 0:
    cX = M['m10'] / M['m00']
    cY = M['m01'] / M['m00']
else:
    cX = 0
    cY = 0

  use the above method to obtain the center point of the circular boundary.

(1) Processing results

▲ figure 2.2.1 processing results

std(rdim1): 0.111475597768182
std(rdim2): 0.12480667032700701
std(rdim3): 0.2491116756143372
std(rdim4): 0.21128501595131527
max(rdim1)-min(rdim1): 0.5198071417283359
max(rdim2)-min(rdim2): 0.6324433245598016
max(rdim3)-min(rdim3): 1.0217870978580805
max(rdim4)-min(rdim4): 0.8341840265537286

  according to the result analysis, this combination method has not achieved obvious results. The results are basically consistent with those obtained by using the boundary center directly.

 

※ general ※ conclusion ※

   this paper discusses whether the accuracy of the ring can be improved by combining the contour area method with the edge brightness curve modeling method in the process of detecting the ring diameter in the metal template. From the test results, it does not show the advantages of the two combination methods.

■ links to relevant literature:

● links to relevant charts:

processing program

#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST1.PY                     -- by Dr. ZhuoQing 2022-01-26
#
# Note:
#============================================================

from headm import *                 # =
import cv2
from tqdm import tqdm
from scipy.optimize     import curve_fit


#------------------------------------------------------------
npzdiag = '/home/aistudio/work/Scanner/ScanDiagBlock.npz'
scandiagdir = '/home/aistudio/work/Scanner/ScanDiagBlock'
#npzdiag = '/home/aistudio/work/Scanner/ScanRowBlock.npz'
#scandiagdir = '/home/aistudio/work/Scanner/ScanRowBlock'
#npzdiag = '/home/aistudio/work/Scanner/ScanVertBlock.npz'
#scandiagdir = '/home/aistudio/work/Scanner/ScanVertBlock'

#filedim = sorted([s for s in os.listdir(scandiagdir) if s.find("jpg") > 0])
#printt(filedim:)

alldata = load(npzdiag, allow_pickle=True)
#printt(alldata.files:)
alldim = alldata['alldim']
allfile = alldata['allfile']

#printt(alldim:, allfile:)

#------------------------------------------------------------

cealldiag = '/home/aistudio/work/Scanner/cealldiag.npz'
cealldata = load(cealldiag, allow_pickle=True)
ceall = cealldata['ceall']

#------------------------------------------------------------

def sigmoidx(x, a,b,c,d):
    return a/(1+exp(-(x-c)*d)) + b



#------------------------------------------------------------
block_side = 140
def img2block(img, circles):
    block = []
    for c in circles:
        left = int(c[0] - block_side)
        right = left + block_side*2
        top = int(c[1] - block_side)
        bottom = top + block_side*2

        block.append(img[top:bottom, left:right, :])

    return block

#------------------------------------------------------------
CIRCLE_NUM          = 100
DELTA_RATIO         = 7
SAMPLE_NUM          = 300
theta = linspace(0, 2*pi, SAMPLE_NUM)
def circleEdges(img, circles, xy):
    clight = []
    for iidd,c in enumerate(circles):
        rdim = linspace(c[-1]-DELTA_RATIO, c[-1]+DELTA_RATIO, CIRCLE_NUM)
        rmean = []
        xx = xy[iidd][0]
        yy = xy[iidd][1]

        for id,r in enumerate(rdim):
            thetadim = []
            for a in theta:
                x = int(xx + r*cos(a))
                y = int(yy + r*sin(a))
                thetadim.append(img[y,x])
            rmean.append(mean(thetadim))
        clight.append(rmean)
    return clight


#------------------------------------------------------------
rdim1 = []
rdim2 = []
rdim3 = []
rdim4 = []

threshold = 100
for id,f in tqdm(enumerate(allfile)):
    img = cv2.imread(f)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


    cc = alldim[id]
    rdim = alldim[id]
    ce = ceall[id]

    block = img2block(img, cc)
    x = linspace(0, 100, 100, endpoint=False)
    xydim = []

    for iidd,b in enumerate(block):
        bgray = cv2.cvtColor(b, cv2.COLOR_BGR2GRAY)
        threshold = mean(bgray.flatten())

        ret,thresh = cv2.threshold(bgray, threshold, 255, 0)
        contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
        cv2.drawContours(b, contours, -1, (0, 0, 255), 3)

        areaDim = []
        momentDim = []

        bcc = cc[iidd]
        bx = bcc[0] - block_side
        by = bcc[1] - block_side

        for id,c in enumerate(contours):
            areaDim.append(cv2.contourArea(c))

            M = cv2.moments(c)
            m00 = M['m00']

            if m00 > 0:
                cX = M['m10'] / M['m00']
                cY = M['m01'] / M['m00']
            else:
                cX = 0
                cY = 0



            momentDim.append((cX + bx,cY + by))

        asorted = sorted(list(zip(areaDim, momentDim)), key=lambda x:x[0])
#        printt(len(asorted))
        a = asorted[-2][0]
        xydim.append(asorted[-2][1])

    #--------------------------------------------------------
#    img = cv2.imread(f)
#    gray = cv2.cvtColor(img, cv2.COLOR_BGR2COLOR)

    ce = circleEdges(gray, cc, xydim )
    x = linspace(0, 100, 100, endpoint=False)
    N = 100
    delta=7
    ratioDim = []
    for i,c in enumerate(ce):
        y = c
#        printt(c:)
        param = (140, 20, 50, 0.2)
        param, conv = curve_fit(sigmoidx, x, y, p0=param)
        r0 = rdim[i][-1]
        rmod = r0 + (param[2] - N/2)*(2*delta/N)
        ratioDim.append(rmod)

    #--------------------------------------------------------
    rdim1.append(ratioDim[0])
    rdim2.append(ratioDim[1])
    rdim3.append(ratioDim[2])
    rdim4.append(ratioDim[3])


#    break


#------------------------------------------------------------
r1a = (array(rdim1) + array(rdim2)) / 2
r2a = (array(rdim3) + array(rdim4)) / 2

printt(max(r1a)-min(r1a):)
printt(max(r2a)-min(r2a):)

#------------------------------------------------------------
plt.clf()
plt.figure(figsize=(10,6))
plt.plot(rdim1, label='Ratio1')
plt.plot(rdim2, label='Ratio2')
plt.plot(rdim3, label='Ratio3')
plt.plot(rdim4, label='Ratio4')
#plt.plot(r1a, label='Big')
#plt.plot(r2a, label='Little')
plt.legend(loc="upper right")
plt.xlabel("n")
plt.ylabel("Ratio")
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()


#------------------------------------------------------------
printt(std(rdim1):,std(rdim2):,std(rdim3):,std(rdim4):)
printt(max(rdim1)-min(rdim1):)
printt(max(rdim2)-min(rdim2):)
printt(max(rdim3)-min(rdim3):)
printt(max(rdim4)-min(rdim4):)


#------------------------------------------------------------
#        END OF FILE : TEST1.PY
#============================================================