Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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
Python 使用openCV对齐图像_Python_Opencv_Homography - Fatal编程技术网

Python 使用openCV对齐图像

Python 使用openCV对齐图像,python,opencv,homography,Python,Opencv,Homography,我收集了大约250张图片。它们都是从一本书中扫描出来的,因此它们都会相互移动或旋转一点。现在,我想对这些图像进行一些数据提取,但为了自动进行提取,所有图像中的所有位置都应该相同。这就是为什么我需要以某种方式对齐这些图像,以便所有图像中的所有位置都相互对应。实现这一目标的最佳方式是什么?我认为openCV是最好的方法,但我不确定该如何开始 以下是扫描图像的示例: 虚线可能是一个很好的定位点 使用箭头将虚线转换为实线 使用 在面具上画线 可以使用遮罩对齐单独的图像。扫描遮罩边缘的坐标,并使用这些

我收集了大约250张图片。它们都是从一本书中扫描出来的,因此它们都会相互移动或旋转一点。现在,我想对这些图像进行一些数据提取,但为了自动进行提取,所有图像中的所有位置都应该相同。这就是为什么我需要以某种方式对齐这些图像,以便所有图像中的所有位置都相互对应。实现这一目标的最佳方式是什么?我认为openCV是最好的方法,但我不确定该如何开始

以下是扫描图像的示例:


虚线可能是一个很好的定位点

  • 使用箭头将虚线转换为实线
  • 使用
  • 在面具上画线
可以使用遮罩对齐单独的图像。扫描遮罩边缘的坐标,并使用这些坐标旋转和移动图像。我的意思是循环通过掩码顶行的值。第一个白色像素给出顶部中心坐标。面具的其他侧面也类似。您可以在不同的图像上比较这些值以确定偏移和旋转。要应用这些转换,请阅读。不过,这需要做相当多的工作。也许有一个更简单的选择:

我可能错了,但似乎您希望对齐页面,以便可以使用硬编码值提取图形。另一种更简单的方法是创建“瓷砖”的子图像。然后可以进一步处理这些问题。这在下面的代码中实现

分离的子图像:

代码:

    import cv2
    import numpy as np  
    # load image
    img_large=cv2.imread("BAgla.jpg")
    # resize for ease of use
    img_ori = cv2.resize(img_large, None, fx=0.2, fy=0.2, interpolation= cv2.INTER_CUBIC)
    # create grayscale
    img = cv2.cvtColor(img_ori, cv2.COLOR_BGR2GRAY)
    # create mask for image size
    mask = np.zeros((img.shape[:2]),dtype=np.uint8)
    # do a morphologic close to merge dotted line
    kernel = np.ones((8,8))
    res = cv2.morphologyEx(img,cv2.MORPH_OPEN, kernel)
    # detect edges for houglines
    edges = cv2.Canny(res, 50,50)
    # detect lines
    lines = cv2.HoughLines(edges,1,np.pi/180,200)
    # draw detected lines
    for line in lines:
            rho,theta = line[0]
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a*rho
            y0 = b*rho
            x1 = int(x0 + 1000*(-b))
            y1 = int(y0 + 1000*(a))
            x2 = int(x0 - 1000*(-b))
            y2 = int(y0 - 1000*(a))

            cv2.line(mask,(x1,y1),(x2,y2),(255),2)
            cv2.line(img,(x1,y1),(x2,y2),(127),2)

    # invert the mask for use with findcontours
    mask_inv = cv2.bitwise_not(mask)
    # use findcontours to get the boundingboxes of the tiles
    contours, hier = cv2.findContours(mask_inv,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    boundingrects = []
    for cnt in contours:
            boundingrects.append(cv2.boundingRect(cnt))

    # findContours has no garanteed order, so sort array
    boundingrects.sort()

    # titles for window names / save file names
    title = ['Kaart', None, 'Smaakprofiel', 'Basiswaarden','Gelijkaardige bieren','Chemisch Profiel']

    # create images for top and bottom tiles
    for index in [0,2,3,5]:
            x,y,w,h = boundingrects[index]
            subimg = img_ori[y:y+h,x:x+w]
            cv2.imshow(title[index], subimg  )

    # combine middle tiles
    x1,y1,w1,h1 = boundingrects[1]
    x2,y2,w2,h2 = boundingrects[4]
    subimg = img_ori[y1:y2+h2,x1:x2+w2]
    cv2.imshow(title[4], subimg  )

    # display result
    cv2.imshow("Result", img  )
    cv2.imshow("Mask", mask  )
    cv2.waitKey(0)
    cv2.destroyAllWindows()

请注意,我使用了缩小版的图像,因此在处理图像时要考虑到这一点。

好的,到目前为止,我了解如何变换和检测线条。但后来你说可以“使用遮罩对齐单独的图像”。我该怎么做呢?你说我可以扫描遮罩边缘的坐标,然后用它们来旋转和移动图像。老实说,我不知道该怎么做。。。我是否应该将这些线的位置从第一个图像应用到所有其他250个图像?或者最好的方法是什么?我倾向于在以下行中得到一个错误
ret,contours,hier=cv2.findContours(mask\u inv,cv2.RETR\u EXTERNAL,cv2.CHAIN\u APPROX\u SIMPLE)
。它说
ValueError:没有足够的值来解包(预期3个,得到2个)
这是因为您有一个更新版本的openCV。只需删除
ret,
,因为该值不再返回:
轮廓,hier=cv2.findContours(mask\u inv,cv2.RETR\u EXTERNAL,cv2.CHAIN\u APPROX\u SIMPLE)
。我还更新了答案好的,谢谢,还有一个问题。您正在缩小图像以便于使用。如果我想从子图像中的图形中提取数据,这有什么影响吗?如果是这样,在使用全尺寸图像时,我应该说明什么?最简单的方法是修改子图像的创建方式。使用
img\u-ori
,而不是
img\u-large
,并将子图像尺寸乘以5(因为图像已缩小到20%)。Unpretty:
subimg=img_大[y*5:y*5+h*5,x*5:x*5+w*5]