如何找到该图像中的螺丝数量?

问题描述 投票:0回答:1

enter image description here

我尝试了二值图像,然后膨胀,但它不起作用,我尝试使用 sift 和 flann 但找不到足够好的 Lowe 比率来获得 95% 的准确度。

import cv2
import numpy as np

img1 = cv2.imread('20240713_194541.jpg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('screw.jpg', cv2.IMREAD_GRAYSCALE)

sift = cv2.SIFT_create()

kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)  # or pass an empty dictionary

flann = cv2.FlannBasedMatcher(index_params, search_params)

matches = flann.knnMatch(des1, des2, k=2)

good_matches = []
for m, n in matches:
    if m.distance < 0.7 * n.distance:
        good_matches.append(m)

img_matches = cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

cv2.imwrite("match.jpg", img_matches)
python opencv image-processing computer-vision object-detection
1个回答
0
投票

就像建议的那样,改进排序/螺钉放置将使这个问题变得更容易。

如果这不是一个选择,并且您需要精确计数,那么小型 ML 模型将是最佳选择。类似于:使用下面的代码检测螺钉组,并在其上应用一些小型检测/回归模型来计算螺钉数量。

假设您可以容忍某种不精确的计数,此代码会估计螺钉的典型尺寸,检测螺钉组并根据组面积估计该组中螺钉的数量。 对于您的图像,它得到正确的螺钉数量。

您可以在此基础上进行改进,使其变得更好(例如,根据团体外观制作

overlap_coef
)。但如果任务发生变化,即使是轻微变化,它也可能会受到限制并且难以移植。

import numpy as np
import cv2
import matplotlib.pyplot as plt 
 

def resize_aspect_ratio(img, height = None):
    original_height, original_width = img.shape[:2]
    new_height = 800
    aspect_ratio = original_width / original_height
    new_width = int(new_height * aspect_ratio)
    return cv2.resize(img, (new_width, new_height))

if __name__ == "__main__":
    
    # Parameters set looking at the histogram below, this is brittle
    min_screw_area = 30
    max_screw_area = 200
    overlap_coef = 1.05 # Blobs of screw looses area because of overlaping, this correct that a little

    img = cv2.imread(r'F:\Data\stack-overflow/H2QY7HOy.jpg')
    img = resize_aspect_ratio(img, 2000) # resize imqge for display + lets not use such a big image for now
    imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, thresh = cv2.threshold(imgray, 127, 255, 0)
    thresh = cv2.bitwise_not(thresh) # inverse the image so that objects of interest are white

    # Find the contours and remove small ones (noise)
    contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    contours = list(filter(lambda cnt: cv2.contourArea(cnt) > min_screw_area, contours)) 

    # Compute contours area and assuming most of the screws are separated compute typical size of a screw
    areas = [cv2.contourArea(cnt) for cnt in contours] 
    median_area_screw = np.median(areas)

    # Number of screws = individual screws + multiple_screw_areas / typical size of a screw
    multiple_screw_areas = list(filter(lambda area: area > max_screw_area, areas))
    num_screws = sum([np.round(area*overlap_coef/median_area_screw ) for area in multiple_screw_areas]) 
    num_screws += len(areas) - len(multiple_screw_areas)

    print(f"Estimated number of screws: {num_screws}")

    # Display some info for experimentation
    for cnt in contours:
        if cv2.contourArea(cnt) > max_screw_area:
            cv2.drawContours(img, [cnt], -1, (0, 255, 0), 1) 
        else:
            cv2.drawContours(img, [cnt], -1, (0, 80, 255), 1) 
    cv2.imshow('Contour', img) 
    plt.hist(areas, bins=100)
    plt.show()
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
© www.soinside.com 2019 - 2024. All rights reserved.