Opencv单应性不会产生所需的转换 [英] Opencv homography does not produce the required tranformation

查看:120
本文介绍了Opencv单应性不会产生所需的转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试沿对象(此处是书)的边缘变换图像.使用Canny边缘检测,我正在检测边缘,并根据像素值从分数矩阵中,选择一个随机4个位于边缘上的坐标进行变换.但是这种转变并不像预期的那样.问题出在哪里/我在哪里错过了?

I am trying to transform an image along the edge of the object (here the object is the book). Using canny edge detection, I am detecting the edges and from the score matrix, based on pixel value, I am choosing a random 4 coordinates lying on the edge for transformation. But the transformation is not as it thought it would be. What is the problem/Where am I missing out?

首先,我将图像的一部分切出.然后应用canny边缘检测并根据我自己的条件随机选择4个边缘坐标点,如下所示: 我的原始图片是:

First I have sliced out a portion of the image. Then applied canny edge detection and randomly selected 4 edge coordinate points based on my own condition as: My original image is:

对于实验,我已根据需要将其切成薄片:

For experiment I have sliced out according to my need as:

此图片的大小(61,160)

现在我需要变换上面的图像,以使书的边缘平行于水平轴.

Now I need to transform the above image to make the edge of the book parallel to the horizontal axis.

img = cv2.imread('download1.jpg',0)
edges = cv2.Canny(img,100,200)
print(img.shape)
plt.show()
plt.imshow(img,cmap='gray')

l=[]
y_list=[]
k=1
for i in range (0,img.shape[0]):
  for j in range (0,img.shape[1]):
    if (edges[i][j]==255) and k<=4 and i>31 and j not in y_list:
      l.append([j,i])
      y_list.append(j)
      k+=1
      break

通过以下方式获得边缘检测图像:

The edge detection image is obtained as:

l列表的内容是

[[49 32]
 [44 33]
 [40 34]
 [36 35]]

然后将列表lt给出的目的地设置为:

Then set the destination points given by list lt as:

[[49 61]
 [44 60]
 [40 61]
 [36 60]]

然后找出单应性矩阵,并用它来找出翘曲透视图:

Then found out the homography matrix and used it to find out the warp perspective as :

h, status = cv2.findHomography(l,lt)
im_out = cv2.warpPerspective(img, h, (img.shape[1],img.shape[0]))

但是不会产生所需的结果!得到的输出图像为:

But it doesnot produce the required result! The resultant output image is obtained as:

推荐答案

我遇到了一个类似的问题,这就是我解决它的方法(实际上与您的方法非常相似),只是我使用的是获取旋转矩阵而不是同质移植: >

I faced a similar issue, and this is how I solved it (quite similar to your method actually), just I used get rotation matrix instead homografy:

  1. 读取图像
  2. 边缘检测器
  3. 用横线获取所有线(在特定间隔内有一个倾斜度)

  1. read image
  2. edge detector
  3. hough line to get all the lines (with an inclination inside a specific interval)

lines = cv.HoughLinesP(img, 1, np.pi/180, 100, minLineLength=100, maxLineGap=10)

  • 获得线的平均倾斜度,因为在我的情况下,我有很多平行线可以用作 引用,通过这种方式,我可以获得更好的结果

  • get lines average inclination, cause in my case I had lot of parallel lines to use as references and in this way I was able to get a better result

     for line in lines:
         x1,y1,x2,y2 = line[0]
         if (x2-x1) != 0:
             angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
         else:
             angle = 90
         #you can skip this test if you have no info about the lines you re looking for
         #in this case offset_angle is = 0
         if min_angle_threshold <= angle <= max_angle_threshold:
            tot_angle = tot_angle + angle
            cnt = cnt + 1
     average_angle = (tot_angle / cnt) - offset_angle 
    

  • 应用反向旋转

  • apply the counter-rotation

      center = your rotation center - probably the center of the image
      rotation_matrix = cv.getRotationMatrix2D(center, angle, 1.0)
      height, width = img.shape
      rotated_image = cv.warpAffine(img, rotation_matrix, (width, height))
    
     #do whatever you want, then rotate image back
     counter_rotation_matrix = cv.getRotationMatrix2D(center, -angle, 1.0)
     original_image = cv.warpAffine( rotated_image, counter_rotation_matrix, (width, height))
    

  • 在此处查看完整示例:

        import math
        import cv2 as cv
    
        img = cv.imread('C:\\temp\\test_3.jpg',0)
        edges = cv.Canny(img,100,200)
        lines = cv.HoughLinesP(edges[0:50,:], 1, np.pi/180, 50, minLineLength=10, maxLineGap=10)
        tot_angle = 0
        cnt = 0
        for line in lines:
            x1,y1,x2,y2 = line[0]
            if (x2-x1) != 0:
                angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
            else:
                angle = 90
    
            if -30 <= angle <= 30:
                tot_angle = tot_angle + angle
                cnt = cnt + 1
        average_angle = (tot_angle / cnt)
        h,w = img.shape[:2]
        center = w/2, h/2
        rotation_matrix = cv.getRotationMatrix2D(center, average_angle, 1.0)
        height, width = img.shape
        rotated_image = cv.warpAffine(img, rotation_matrix, (width, height))
        cv.imshow("roto", rotated_image)
        #do all your stuff here, add text and whatever
        #...
        #...
        counter_rotation_matrix = cv.getRotationMatrix2D(center, -average_angle, 1.0)
        original_image = cv.warpAffine( rotated_image, counter_rotation_matrix, (width, height))
        cv.imshow("orig", original_image)
    

    旋转

    ] counter_rotated

    counter_rotated

    ]

    如果要应用单应性(不同于简单的旋转,因为它还应用了透视变换),请在代码下方使其生效:

    in case you want apply an homography(different than just a simple rotation, 'cause it also applies a perspective transformation), below the code to make it work:

    #very basic example, similar to your code with fixed terms
    l  = np.array([(11,32),(43,215),(142,1),(205,174)])
    lt = np.array([(43,32),(43,215),(205,32),(205,215)])
    h, status = cv.findHomography(l,lt)
    im_out = cv.warpPerspective(img, h, (img.shape[1],img.shape[0]))
    

    以编程方式进行 -对于"l":也要使用粗线,找到4个角, 然后添加它们

    To do it programmatically - for "l" : just use houghlines as well and find the 4 corners, then add them

    • 表示"lt":找到所有4个点的终点",例如,使用底角作为参考

    • for "lt": find a "destination" for all the 4 points, for instance use the bottom corners as reference

    lines = cv.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=150, maxLineGap=5)
    l = []
    for line in lines:
        x1,y1,x2,y2 = line[0]
    
        if (x2-x1) != 0:
            angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
        else:
            angle = 90
        # consider only vertical edges
        if 60 <= angle:
            l.append((x1,y1))
            l.append((x2,y2))
            x_values.append(max(x1,x2)) 
            if len(y_values) == 0:
                y_values.append(y1)
                y_values.append(y2)
    l  = np.array(l)
    lt = np.array([(x_values[0],y_values[0]),(x_values[0],y_values[1]),(x_values[1],y_values[0]),(x_values[1],y_values[1])])
    

    然后按上述方法调用findhomography 希望已经足够清楚了!

    then call findhomography as done above Hope it's clear enough!

    查看全文

    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆