2017-06-20 141 views
3

注:我正在尝试制作一个可以处理一般范围的图像,方向和质量的过程,而不仅仅是这个图像。任何形状四边形的最小包围盒或凸包?

我知道你可以使用凸包来用一个多边形包围一组点,并且你可以使用几种算法之一为这些点创建一个最小边界框。但是,我想要做的是与最小边界框类似,但不限制为矩形。

说我有此收据:

enter image description here

凸包:

enter image description here

的最小边界框(旋转钳):

enter image description here

我的目标:(MS-漆):

enter image description here

正如你所看到的最小边界框完全不是那么回事了,因为收据是从梯形视角。视角越低,情况越糟糕。我想要4点和尖角,所以我不能使用凸包。

是否有一种算法可以用来获得类似于凸包或最小边界框但只限于4个点和任何四边形的东西?

+0

为什么不Harris角检测?或者用你当前的算法,你可以拒绝来自凸包的小线,并找到长线的交点。使用这两个端点,您可以找到交叉点[使用决定因素](https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line)。或者,您可以保留所有从凸包获得的点并使用['kmeans' clustering](http://docs.opencv.org/3.0-beta/modules/core/doc/clustering.html)来查找那4分并称你的分数。 –

+1

查看我的答案[这里](https://stackoverflow.com/questions/44449871/fine-tuning-hough-line-function-parameters-opencv/44454619#44454619)的一个例子,用Hough Lines做交集群。我认为找到轮廓可能会更好,然后再用线条找出交点,就像我在那个答案中做的那样。 –

+0

@AlexanderReynolds好主意。现在我生成轮廓,逼近它们,凸出它们,然后查找最小边界框。我不想使用凸包或轮廓线的唯一原因是您的边缘非常圆或翘曲,形状笨拙的收据。霍夫线是一种替代方案,但我可以从文本中获得数百行和数百行,即使在边缘检测之前模糊和平滑之后。如果我想改善这一点,那将是另一个问题。在那里编辑好的答案,看起来很有希 –

回答

1

随着色彩空间过滤和形态学操作的一些混乱,我能够成功地使用哈里斯探测器。你也可以使用交点来展开这个交点,比如我从Hough Lines中做了here,这可能很有用,尽管有点冗长。这对于这个特定的图像来说效果很好,但对于一个管道来说,它需要很多参数(打开和关闭内核大小,迭代)。

我的实现是Python,但这个当然可以用C++或Java以及工作:

import numpy as np 
import cv2 

# read image 
img = cv2.imread('receipt.png') 

# thresholding 
blur = cv2.GaussianBlur(img, (5,5), 1) 
hls = cv2.cvtColor(blur, cv2.COLOR_BGR2HLS) 
low = np.array([0, 70, 0]) 
high = np.array([255, 255, 85]) 
thresh = cv2.inRange(hls, low, high) 

# morphological operations to get the paper 
kclose = np.ones((3,3), dtype=np.uint8) 
kopen = np.ones((5,5), dtype=np.uint8) 
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kclose, iterations=2) 
opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kopen, iterations=6) 

# corner detection 
opening = cv2.GaussianBlur(opening, (3,3), 1) 
opening = np.float32(opening) 
dst = cv2.cornerHarris(opening, 2, 3, 0.04) 

# drawing corners 
dst = cv2.dilate(dst, None) 
img[dst>0.01*dst.max()]=[0,0,255] 

cv2.imshow('Corners', img) 
cv2.waitKey(0) 

而这里的角落:

Corners

请注意,您收到多个像素来自哈里斯,所以如果你想在之后使用它们进行翘曲的话,你必须进行聚类来获得单数的角点。

我从图像中的颜色空间过滤,关闭和打开应用了蒙版,以便您可以在这些操作之后看到蒙版。

过滤:

Filtering

闭幕:

Closing

开幕:

Opening

+0

谢谢alex!我现在正在经历这个。你为什么选择你做的低/高颜色?那是任意的,特定于这个图像还是标准?如果它仅仅是这张图片的特定部分,是否会有一种方法来尝试确定给定图像的低/高应该是什么? –

+0

完全特定于此图片。如果不具体了解可能的背景,尝试自动过滤通常很困难。如果你正在开发一个应用程序,可以使用任何背景,这种方法不是很健壮。你应该在不同的颜色空间中进行试验,以了解每种颜色对应白色和浅灰色的感觉。对于任意图像,更容易继续使用您的原始方法 - 轮廓,并按照我在您的问题的评论中建议的方式跟随它们到角落。 –