【问题标题】:Assigning scores to bullet holes on a simple ringed target为简单环形目标上的弹孔分配分数
【发布时间】:2021-05-13 12:24:15
【问题描述】:

我目前正在开展一个项目,以检测和评分简单环形目标上的弹孔。 我现在拥有的代码根据轮廓的中心为孔分配一个分数。这是我正在使用的Target1

如果轮廓与较高区域的边界重叠,我希望它被分配更高的分数,而不管中心在哪里。示例如下:

]2

我的程序的代码和输出如下所示,其中分数是分别分配的中心而不是重叠的边界:

from cv2 import cv2
import numpy as np
import imutils

def centroid(contour):
    M = cv2.moments(contour)
    cx = int(round(M['m10']/M['m00']))
    cy = int(round(M['m01']/M['m00']))
    centre = (cx, cy)
    return centre

def getScore(scoreboundaries, HoleDist): #function to assign a score to each hole

    score = 0

    if scoreboundaries[0]>HoleDist:
        score = 10
    for i in range(1, len(scoreboundaries)):
        if scoreboundaries[i-1]<=HoleDist<scoreboundaries[i]:
            score = len(scoreboundaries) - i
    return score


default = cv2.imread("3.jpg")
img = cv2.resize(default,(640,640))

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)

v_mask = cv2.inRange(v, 0, 155)

cnts = cv2.findContours(v_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

for c in cnts:

    if cv2.contourArea(c) > 10000: 
        cv2.drawContours(img, [c], -1, (0, 255, 0), 2)
        area_max = cv2.contourArea(c) 
        
radius_max = np.sqrt(area_max / np.pi)
section_size = radius_max / 9

centre_v_mask = cv2.inRange(v, 215, 255)
cnts = cv2.findContours(centre_v_mask.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

for c in cnts:
    if cv2.contourArea(c) > 10:
        centre_coords = centroid(c)
       
h_mask = cv2.inRange(h, 0, 30)
h_mask = cv2.medianBlur(h_mask, 11)
cnts = cv2.findContours(h_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

holes = []
HoleDists = []


scoreboundaries = []
for i in range(1,10): #calculate other rings
    
    cv2.circle(img, centre_coords, int(i*(section_size)), (255, 0, 0), 1)
    scoreboundaries.append(int(i*(section_size)))

for c in cnts: #plot bullet holes

    if cv2.contourArea(c) > 1:
        x,y,w,h = cv2.boundingRect(c)
        pts =[(x, y), (x+w, y), (x, y+h), (x+w, y+h)]

        centre_holes = centroid(c)
        pts.append(centre_holes)

        pointscore = 0
        for pt in pts: 
            X = pt[0]
            Y = pt[1]
            
            HoleDist = np.sqrt((X-centre_coords[0])**2 + (Y - centre_coords[1])**2)
            HoleDists.append(HoleDist)
            score = getScore(scoreboundaries, HoleDist)

            if score>pointscore:
                pointScore = score

        cv2.circle(img, (centre_holes), 1, (0, 0, 255), -1)
        cv2.rectangle(img, (x,y),(x+w,y+h),(0,0,255),2)
        cv2.drawContours(img, [c], -1, (0, 255, 0), 1)
        

        cv2.putText(img, "Score: " + str(pointScore), (centre_holes[0] - 20, centre_holes[1] + 20),
        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

cv2.imshow('frame', img)
cv2.waitKey(0)

我想知道我哪里出错了。感谢所有帮助,谢谢。

【问题讨论】:

    标签: python opencv image-processing contour


    【解决方案1】:

    这是一个经典的 Python 错误。您将pointscore 大写:

    pointScore = score
    cv2.putText( img, "Score: " + str(pointScore) ....
    

    所以你实际上只是在使用你看到的最后一个分数,因为pointscore 总是0pointScore = score

    这是修正了这两个错别字的图片。还要记住,OpenCV 轮廓只是一组连接在一起的点。如果需要,您可以使用相同的评分代码来迭代轮廓点。

    如果你想换成使用轮廓点,这是一个很小的变化。

    改变这个:

    for pt in pts: 
        X = pt[0]
        Y = pt[1]
    

    到这里:

    for pt in c:
        pt = pt[0] # contour points have an extra pair of brackets [[x,y]] 
        X = pt[0]
        Y = pt[1]
    

    【讨论】:

    • 感谢您的帮助和建议!你能证明这一点吗?我理解它背后的逻辑,但我似乎无法实现它。我对 python opencv 很陌生,所以我仍然习惯于语法。提前谢谢你
    猜你喜欢
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 2021-09-19
    • 2017-03-29
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    相关资源
    最近更新 更多