ValueError: too many values to unpack (expected 4) during ORB detection

ValueError: too many values to unpack (expected 4) during ORB detection

我正在检测星空背景上的 Unicode 字词。它们看起来都有点像下面的示例图片。我有一个包含 183 张图像的文件夹,如果检测到其中任何图像,我想单击屏幕上的按钮。如果没有检测到图像,我想重复这个过程。

到目前为止,我在模板匹配方面取得了最大的成功。我将图像加载到一个数组中,遍历整个数组,如果有 returns >90% 匹配,我单击按钮。

然而,这会返回大量误报。为了改进我的检测,我已经尝试过;

远射的最佳结果是使用 ORB,毫无疑问,甚至没有接近。

我已经关注 this tutorial and all of the tutorials on opencv.org,但是 我收到以下错误,这似乎是相当随机的。通常是当后台应用程序图像发生显着变化时,但我不知道为什么这很重要。

    Traceback (most recent call last):
      File "c:\Users\keypoint_detection_test1.py", line 63, in <module>
        keypoint_detection(ships_to_avoid)
      File "c:\Users\keypoint_detection_test1.py", line 39, in keypoint_detection
        kp1, kp2, matches, match_points = objectToFind.match_keypoints(keypoint_image)
    ValueError: too many values to unpack (expected 4)

这个错误是什么意思,我该如何解决?

import cv2 as cv
import os
import glob
    
# Change the working directory to the folder this script is in.
os.chdir('C:\Users\')

avoid = glob.glob(r"C:\Users\*.png")

def loadImages(directory):
    # Intialise empty array
    image_list = []
    # Add images to array
    for i in directory:
        img = cv.imread(i, cv.IMREAD_UNCHANGED)
        image_list.append((img, i))
    return image_list

# initialize the WindowCapture class
wincap = WindowCapture()

def keypoint_detection(image_list):

    for i in image_list:
        needle_img = i[0]
        needle_name = i[1]

        # load image to find
        objectToFind = Vision(needle_img)
        # get an updated image of the screen
        keypoint_image = wincap.get_haystack()
        # crop the image
        x, w, y, h = [600,700,20,50]
        keypoint_image = keypoint_image[y:y+h, x:x+w]

        kp1, kp2, matches, match_points = objectToFind.match_keypoints(keypoint_image)
        match_image = cv.drawMatches(objectToFind.needle_img, kp1, keypoint_image, kp2, matches, None)

        if match_points:
            # find the center point of all the matched features
            center_point = objectToFind.centeroid(match_points)
            # account for the width of the needle image that appears on the left
            center_point[0] += objectToFind.needle_w
            # drawn the found center point on the output image
            match_image = objectToFind.draw_crosshairs(match_image, [center_point])

            # move somewhere/do something
            #py.moveTo(center_point)

        # display the processed image
        cv.imshow('Keypoint Search', match_image)

        # press 'q' with the output window focused to exit.
        if cv.waitKey(1) == ord('q'):
            cv.destroyAllWindows()
    

while(True):
    ships_to_avoid = loadImages(avoid)
    keypoint_detection(ships_to_avoid)
class Vision:

    # properties
    needle_img = None
    needle_w = 0
    needle_h = 0

    # constructor
    def __init__(self, needle_img_path):
        self.needle_img = needle_img_path 

        # Save the dimensions of the needle image
        self.needle_w = self.needle_img.shape[1]
        self.needle_h = self.needle_img.shape[0]

    def match_keypoints(self, original_image, patch_size=32):
        min_match_count = 35

        orb = cv.ORB_create(edgeThreshold=0, patchSize=patch_size)
        keypoints_needle, descriptors_needle = orb.detectAndCompute(self.needle_img, None)
        orb2 = cv.ORB_create(edgeThreshold=0, patchSize=patch_size, nfeatures=2000)
        keypoints_haystack, descriptors_haystack = orb2.detectAndCompute(original_image, None)

        FLANN_INDEX_LSH = 6
        index_params = dict(algorithm=FLANN_INDEX_LSH, table_number=6, key_size=12, multi_probe_level=1)
        search_params = dict(checks=50)

        try:
            flann = cv.FlannBasedMatcher(index_params, search_params)
            matches = flann.knnMatch(descriptors_needle, descriptors_haystack, k=2)
        except cv.error:
            return None, None, [], [], None

        # store all the good matches as per Lowe's ratio test.
        good = []
        points = []

        for pair in matches:
            if len(pair) == 2:
                if pair[0].distance < 0.7*pair[1].distance:
                    good.append(pair[0])

        if len(good) > min_match_count:
            print('match %03d, kp %03d' % (len(good), len(keypoints_needle)))
            for match in good:
                points.append(keypoints_haystack[match.trainIdx].pt)
        
        return keypoints_needle, keypoints_haystack, good, points
class WindowCapture:

    # properties
    w = 0
    h = 0
    hwnd = None
    cropped_x = 0
    cropped_y = 0
    offset_x = 0
    offset_y = 0

    # constructor
    def __init__(self, window_name=None):
        # find the handle for the window we want to capture.
        # if no window name is given, capture the entire screen
        if window_name is None:
            self.hwnd = win32gui.GetDesktopWindow()
        else:
            self.hwnd = win32gui.FindWindow(None, window_name)
            if not self.hwnd:
                raise Exception('Window not found: {}'.format(window_name))

        # get the window size
        window_rect = win32gui.GetWindowRect(self.hwnd)
        self.w = window_rect[2] - window_rect[0]
        self.h = window_rect[3] - window_rect[1]

        # account for the window border and titlebar and cut them off
        border_pixels = 0
        titlebar_pixels = 0
        self.w = self.w - (border_pixels * 2)
        self.h = self.h - titlebar_pixels - border_pixels
        self.cropped_x = border_pixels
        self.cropped_y = titlebar_pixels

        self.offset_x = window_rect[0] + self.cropped_x
        self.offset_y = window_rect[1] + self.cropped_y

    def get_haystack(self):

        # get the window image data
        wDC = win32gui.GetWindowDC(self.hwnd)
        dcObj = win32ui.CreateDCFromHandle(wDC)
        cDC = dcObj.CreateCompatibleDC()
        dataBitMap = win32ui.CreateBitmap()
        dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h)
        cDC.SelectObject(dataBitMap)
        cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY)

        signedIntsArray = dataBitMap.GetBitmapBits(True)
        img = np.fromstring(signedIntsArray, dtype='uint8')
        img.shape = (self.h, self.w, 4)

        # free resources
        dcObj.DeleteDC()
        cDC.DeleteDC()
        win32gui.ReleaseDC(self.hwnd, wDC)
        win32gui.DeleteObject(dataBitMap.GetHandle())
        img = img[...,:3]
        img = np.ascontiguousarray(img)
        return img

match_keypoints 中你有(至少)两个 return 语句。

其中一个,在except块中returns 5个元素,None, None, [], [], None.

其他returns 4个元素,return keypoints_needle, keypoints_haystack, good, points

因此,每当 match_keypoints 在那个 try 块中遇到 cv.error 时,它将 return 5 个元素,这比你试图在该行中取消引用多一个那是失败的:kp1, kp2, matches, match_points = objectToFind.match_keypoints(keypoint_image)

Too many values to unpack 是当 returned 元组的元素多于分配的 LHS 上的变量数时发生的错误。