我已经使用OpenCV函数和C++将两个图像拼接在一起。现在我面临一个问题,即最终的图像包含一个大的黑色部分。如何从图像中删除黑色部分?
最终图像应该是包含有效部分的矩形。 我的形象是:
如何删除黑色款?
我已经使用OpenCV函数和C++将两个图像拼接在一起。现在我面临一个问题,即最终的图像包含一个大的黑色部分。如何从图像中删除黑色部分?
最终图像应该是包含有效部分的矩形。 我的形象是:
如何删除黑色款?
mevatron
的答案是黑色区域的数量最小化同时保留完整图像的一种方法。
另一种选择是去除完整的黑色区域,在这个区域中也会丢失图像的某些部分,但结果会是一个整齐的长方形图像。以下是Python代码。
在这里,你会发现图像的三个主要的角落如下:
我已标记的值。 (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),你得到的结果如下:
因此,您裁剪图像以纠正矩形区域。
img2 = img[:y,:x].copy()
下面是结果:
See, the problem is that you lose some parts of the stitched image.
:因为我更熟悉C++,并试图将代码(在Python中)转换为C++,但无法成功。如果您可以请C++语言共享相同的代码,我会非常感激。 –
我很抱歉,我不擅长C++。但如果你告诉我,如果你对我的方法中的任何步骤有任何疑问,我可以用更简单的方式解释。 –
:我已经完成了所有的步骤,直到approxpolyDP,但我不知道如何计算C中坐标点的乘积,我认为你也使用了伪代码。可以告诉我如何计算C中坐标点的乘积或者给我任何链接,其中有人使用了你的C类型的方法。在应用approxpoly()方法后,我的图像是参考[http://i.imgur.com/Qfoyt.jpg?1]。希望你也得到了应用approxpolyDp()后的输出图像相同。 –
您可以使用threshold,findContours和boundingRect来做到这一点。
所以,这里是一个快速的脚本,用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]]
最终看起来像这样:
注:排序可能没有必要用生图像,但使用压缩图像引起了一些压缩伪像使用低阈值时展现出来,所以这就是为什么我使用排序进行后处理。
希望有帮助!
+1伟大的工作示例。 – karlphillip
你也许可以使用cvFindContours让您的图像内容的范围,然后裁剪到... – LiMuBei
同时加入图片在问题中,使用'imwrite'输出结果并添加它。这比添加屏幕截图要好,因为那些回答你问题的人需要从图像中删除不需要的区域。 –
您的工作区很整洁。 – wengseng