我使用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()
下一个 (x1,1)。这是第二个元素为1的点,然后第一个元素是最大值。
xmax = approx[approx[:,:,1]==1].max()
现在我们要找到在 (far.x, xmax) 和 (far.y, ymax) 中的 最小值
x = min(far[0],xmax)
y = min(far[1],ymax)
如果你用 (1,1) 和 (x,y) 绘制一个矩形,你会得到下面的结果:
因此,你需要裁剪图像以获得正确的矩形区域。
img2 = img[:y,:x].copy()
以下是结果:
问题在于您会丢失一些拼接图像的部分。
cv2.approxPolyDP()
和cv2.arcLength()
相对应的函数时遇到了麻烦。你的方法正是我需要的,但是在这些函数上卡住了。请看一下我的问题,链接在这里http://stackoverflow.com/questions/35170367/how-to-find-black-patch-in-an-image-in-matlab - Nancystitched = 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]]
您可以使用主动轮廓(气球/蛇线)精确选择黑色区域。您可以在这里找到演示链接。OpenCV中提供了主动轮廓,请查看cvSnakeImage。
imwrite
输出结果并添加。这比添加截图更好,因为回答你的问题的人需要从图像中删除不必要的区域。 - Abid Rahman K