Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用OpenCV检测图像中已知形状/对象的方法 我的任务是用OpenCV来检测给定图像中的对象(我不关心它是Python还是C++实现)。下面三个示例中显示的对象是一个黑色矩形,其中包含五个白色矩形。所有尺寸都是已知的_Python_C++_Opencv_Image Processing - Fatal编程技术网

使用OpenCV检测图像中已知形状/对象的方法 我的任务是用OpenCV来检测给定图像中的对象(我不关心它是Python还是C++实现)。下面三个示例中显示的对象是一个黑色矩形,其中包含五个白色矩形。所有尺寸都是已知的

使用OpenCV检测图像中已知形状/对象的方法 我的任务是用OpenCV来检测给定图像中的对象(我不关心它是Python还是C++实现)。下面三个示例中显示的对象是一个黑色矩形,其中包含五个白色矩形。所有尺寸都是已知的,python,c++,opencv,image-processing,Python,C++,Opencv,Image Processing,但是,图像的旋转、比例、距离、透视、照明条件、相机焦距/镜头和背景未知。黑色矩形的边缘不能保证是完全可见的,但是在五个白色矩形之前不会有任何东西——它们总是完全可见的。最终目标是能够检测图像中该对象的存在,并旋转、缩放和裁剪以显示移除透视图的对象。考虑到物体的四个角,我很有信心我可以调整图像,使其仅裁剪到物体。然而,我不太相信我能可靠地找到这四个角落。在模棱两可的情况下,与其将图像的某些其他特征误识别为对象,不如不找到对象 使用OpenCV,我想出了以下方法,但是我觉得我可能遗漏了一些明显的东西

但是,图像的旋转、比例、距离、透视、照明条件、相机焦距/镜头和背景未知。黑色矩形的边缘不能保证是完全可见的,但是在五个白色矩形之前不会有任何东西——它们总是完全可见的。最终目标是能够检测图像中该对象的存在,并旋转、缩放和裁剪以显示移除透视图的对象。考虑到物体的四个角,我很有信心我可以调整图像,使其仅裁剪到物体。然而,我不太相信我能可靠地找到这四个角落。在模棱两可的情况下,与其将图像的某些其他特征误识别为对象,不如不找到对象

使用OpenCV,我想出了以下方法,但是我觉得我可能遗漏了一些明显的东西。是否还有其他方法可用,或者其中一种是最佳解决方案

基于边缘的轮廓 第一个想法是寻找物体的外部边缘

使用Canny边缘检测(在缩放到已知大小、灰度缩放和高斯模糊后),找到与对象外部形状最匹配的轮廓。 这涉及到透视、颜色、大小等问题,但如果存在复杂的背景,或者图像中其他地方存在与对象形状相似的东西,则会失败。也许这可以通过一套更好的规则来找到正确的轮廓来改善——可能包括五个白色矩形以及外部边缘

特征检测 下一个想法是使用特征检测与已知模板匹配

使用ORB特征检测、描述符匹配和单应性()失败,我认为这是因为它检测的特征与对象中的其他特征非常相似(许多Corener精确地说是四分之一的白色和四分之三的黑色)。然而,我确实喜欢与已知模板匹配的想法——这个想法对我来说很有意义。我想,因为对象在几何上非常基本,所以在特征匹配步骤中可能会发现很多误报

平行线 使用Houghlines或HoughLinesP,查找等间距的平行线。我刚刚开始这条路,因此需要研究阈值等的最佳方法。虽然复杂背景的图像看起来很混乱,但我认为它可能会很好地工作,因为我可以依赖这样一个事实,即黑色对象中的白色矩形应始终具有高对比度,可以很好地指示线条的位置

“条形码扫描” 我的最终想法是逐行扫描图像,寻找从白色到黑色的图案

我还没有开始使用这种方法,但我的想法是从图像上取一条带(以某个角度),转换为HSV颜色空间,然后寻找在值列中连续出现五次的规则黑白图案。这个想法听起来很有希望,因为我认为它应该忽略许多未知变量

思想 我看了很多OpenCV教程,还有一些问题,例如,因为我的对象在几何上非常简单,所以我在实现给定的想法时遇到了问题

我觉得这是一项可以完成的任务,但我的奋斗目标是知道进一步采用哪种方法。我对前两个想法做了很多实验,虽然我还没有取得任何非常可靠的成果,但也许我还缺少一些东西。是否有一种我没有想到的标准方法来完成这项任务,或者我建议的方法之一是最明智的

编辑:一旦使用上述方法之一(或其他方法)找到角点,我会考虑使用Hu矩或OpenCV的matchShapes()函数来消除任何误报

EDIT2:根据@Timo的要求添加了更多的输入图像示例



我花了一些时间研究这个问题,并编写了一个小python脚本。我在检测你的形状里面的白色矩形。将代码粘贴到.py文件中,并复制输入子文件夹中的所有输入图像。图像的最终结果只是一个虚拟atm,脚本还没有完成。在接下来的几天里,我会继续努力。脚本将创建一个调试子文件夹,在其中保存一些显示当前检测状态的图像

import numpy as np
import cv2
import os

INPUT_DIR = 'input'
DEBUG_DIR = 'debug'
OUTPUT_DIR = 'output'
IMG_TARGET_SIZE = 1000

# each algorithm must return a rotated rect and a confidence value [0..1]: (((x, y), (w, h), angle), confidence)

def main():
    # a list of all used algorithms
    algorithms = [rectangle_detection] 

    # load and prepare images
    files = list(os.listdir(INPUT_DIR))
    images = [cv2.imread(os.path.join(INPUT_DIR, f), cv2.IMREAD_GRAYSCALE) for f in files]
    images = [scale_image(img) for img in images]

    for img, filename in zip(images, files):
        results = [alg(img, filename) for alg in algorithms]
        roi, confidence = merge_results(results)

        display = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
        display = cv2.drawContours(display, [cv2.boxPoints(roi).astype('int32')], -1, (0, 230, 0))            
        cv2.imshow('img', display)
        cv2.waitKey()


def merge_results(results):
    '''Merges all results into a single result.'''
    return max(results, key=lambda x: x[1]) 

def scale_image(img):    
    '''Scales the image so that the biggest side is IMG_TARGET_SIZE.'''
    scale = IMG_TARGET_SIZE / np.max(img.shape)
    return cv2.resize(img, (0,0), fx=scale, fy=scale)     


def rectangle_detection(img, filename):    
    debug_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    _, binarized = cv2.threshold(img, 50, 255, cv2.THRESH_BINARY)    
    contours, _ = cv2.findContours(binarized, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    # detect all rectangles
    rois = []
    for contour in contours:
        if len(contour) < 4:
            continue
        cont_area = cv2.contourArea(contour)
        if not 1000 < cont_area < 15000: # roughly filter by the volume of the detected rectangles
            continue
        cont_perimeter = cv2.arcLength(contour, True)
        (x, y), (w, h), angle = rect = cv2.minAreaRect(contour)
        rect_area = w * h
        if cont_area / rect_area < 0.8: # check the 'rectangularity'
            continue        
        rois.append(rect)

    # save intermediate results in the debug folder
    rois_img = cv2.drawContours(debug_img, contours, -1, (0, 0, 230))
    rois_img = cv2.drawContours(rois_img, [cv2.boxPoints(rect).astype('int32') for rect in rois], -1, (0, 230, 0))
    save_dbg_img(rois_img, 'rectangle_detection', filename, 1)

    # todo: detect pattern

    return rois[0], 1.0 # dummy values


def save_dbg_img(img, folder, filename, index=0):
    '''Writes the given image to DEBUG_DIR/folder/filename_index.png.'''
    folder = os.path.join(DEBUG_DIR, folder)
    if not os.path.exists(folder):
        os.makedirs(folder)
    cv2.imwrite(os.path.join(folder, '{}_{:02}.png'.format(os.path.splitext(filename)[0], index)), img)


if __name__ == "__main__":
    main()
将numpy导入为np
进口cv2
导入操作系统
INPUT_DIR='INPUT'
DEBUG_DIR='DEBUG'
OUTPUT_DIR='OUTPUT'
IMG_目标尺寸=1000
#每个算法必须返回一个旋转的rect和一个置信值[0..1]:((x,y),(w,h),角度),置信度)
def main():
#所有使用的算法的列表
算法=[矩形_检测]
#加载并准备图像
files=list(os.listdir(INPUT_DIR))
images=[cv2.imread(os.path.join(INPUT_DIR,f),cv2.imread_GRAYSCALE)用于文件中的f]
图像=[图像中img的缩放图像(img)]
对于img,zip格式的文件名(图像、文件):
结果=[alg(img,文件名)用于算法中的alg]
roi,置信度=合并结果(结果)
显示=cv2.CVT颜色(img,cv2.COLOR_GRAY2BGR)
display=cv2.drawContours(显示[cv2.boxPoints(roi).astype('int32')]),-1,(0,230,0))
cv2.imshow(“img”,显示)
cv2.waitKey()
def合并_结果(结果):
''将所有结果合并为一个结果''
返回最大值(结果,键=λx:x[1])
def缩放图像(img):
“缩放图像,使最大的一面为IMG_目标尺寸。”
sc