2012-05-17 137 views
10

我已经使用OpenCV函数和C++将两个图像拼接在一起。现在我面临一个问题,即最终的图像包含一个大的黑色部分。如何从图像中删除黑色部分?

最终图像应该是包含有效部分的矩形。 我的形象是:

enter image description here

如何删除黑色款?

+0

你也许可以使用cvFindContours让您的图像内容的范围,然后裁剪到... – LiMuBei

+2

同时加入图片在问题中,使用'imwrite'输出结果并添加它。这比添加屏幕截图要好,因为那些回答你问题的人需要从图像中删除不需要的区域。 –

+4

您的工作区很整洁。 – wengseng

回答

16

mevatron的答案是黑色区域的数量最小化同时保留完整图像的一种方法。

另一种选择是去除完整的黑色区域,在这个区域中也会丢失图像的某些部分,但结果会是一个整齐的长方形图像。以下是Python代码。

在这里,你会发现图像的三个主要的角落如下:

enter image description here

我已标记的值。 (1,x2), (x1,1), (x3,y3)。它基于你的图像从(1,1)开始的假设。

代码:

第一步骤同mevatron的。模糊图像以去除噪点,对图像进行阈值处理,然后查找轮廓。

import cv2 
import numpy as np 

img = cv2.imread('office.jpg') 
img = cv2.resize(img,(800,400)) 

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
gray = cv2.medianBlur(gray,3) 

ret,thresh = cv2.threshold(gray,1,255,0) 
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 

现在找到最大的轮廓,这是你的形象。这是为了避免噪音,如果有的话(很可能不会有)。或者你可以使用mevatron的方法。

max_area = -1 
best_cnt = None 

for cnt in contours: 

    area = cv2.contourArea(cnt) 
    if area > max_area: 
     max_area = area 
     best_cnt = cnt 

现在近似轮廓以删除找到的轮廓值中不必要的点,但它保留所有角值。

approx = cv2.approxPolyDP(best_cnt,0.01*cv2.arcLength(best_cnt,True),True) 

现在我们找到了角落。

首先,我们找到(x3,y3)。这是最远的点。所以x3*y3将会非常大。所以我们找到所有对点的产品并选择最大产品对。

far = approx[np.product(approx,2).argmax()][0] 

Next(1,x2)。这是第一个元素是一个,然后第二个元素是最大的点。

ymax = approx[approx[:,:,0]==1].max() 

Next(x1,1)。它是第二个元素是1的点,那么第一个元素是最大的。

xmax = approx[approx[:,:,1]==1].max() 

现在我们找到了minimum values in (far.x,xmax) and (far.y, ymax)

x = min(far[0],xmax) 
y = min(far[1],ymax) 

如果您绘制(1,1)的矩形和(X,Y),你得到的结果如下:

enter image description here

因此,您裁剪图像以纠正矩形区域。

img2 = img[:y,:x].copy() 

下面是结果:

enter image description here

See, the problem is that you lose some parts of the stitched image.

+1

:因为我更熟悉C++,并试图将代码(在Python中)转换为C++,但无法成功。如果您可以请C++语言共享相同的代码,我会非常感激。 –

+0

我很抱歉,我不擅长C++。但如果你告诉我,如果你对我的方法中的任何步骤有任何疑问,我可以用更简单的方式解释。 –

+0

:我已经完成了所有的步骤,直到approxpolyDP,但我不知道如何计算C中坐标点的乘积,我认为你也使用了伪代码。可以告诉我如何计算C中坐标点的乘积或者给我任何链接,其中有人使用了你的C类型的方法。在应用approxpoly()方法后,我的图像是参考[http://i.imgur.com/Qfoyt.jpg?1]。希望你也得到了应用approxpolyDp()后的输出图像相同。 –

0

您可以使用活动轮廓(气球/蛇)来精确选择黑色区域。示范可以发现here。 OpenCV提供活动轮廓,请查询cvSnakeImage

+0

你能告诉我如何实施它去除黑色部分吗? –

8

您可以使用thresholdfindContoursboundingRect来做到这一点。

所以,这里是一个快速的脚本,用python界面做这件事。

stitched = cv2.imread('stitched.jpg', 0) 
(_, mask) = cv2.threshold(stitched, 1.0, 255.0, cv2.THRESH_BINARY); 

# findContours destroys input 
temp = mask.copy() 
(contours, _) = cv2.findContours(temp, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 

# sort contours by largest first (if there are more than one) 
contours = sorted(contours, key=lambda contour:len(contour), reverse=True) 
roi = cv2.boundingRect(contours[0]) 

# use the roi to select into the original 'stitched' image 
stitched[roi[1]:roi[3], roi[0]:roi[2]] 

最终看起来像这样: enter image description here

注:排序可能没有必要用生图像,但使用压缩图像引起了一些压缩伪像使用低阈值时展现出来,所以这就是为什么我使用排序进行后处理。

希望有帮助!

+0

+1伟大的工作示例。 – karlphillip

相关问题