13

I have stitched two images together using OpenCV functions and C++. Now I am facing a problem that the final image contains a large black part.

The final image should be a rectangle containing the effective part. My image is the following:

enter image description here

How can I remove the black section?

4

3 回答 3

22

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

另一种选择是删除完整的黑色区域,您也会丢失图像的某些部分,但结果将是一个看起来整洁的矩形图像。下面是 Python 代码。

在这里,您可以找到图像的三个主要角,如下所示:

在此处输入图像描述

我已经标记了这些值。(1,x2), (x1,1), (x3,y3). 它基于您的图像从 (1,1) 开始的假设。

代码 :

第一步与mevatron's 相同。模糊图像以去除噪声,对图像进行阈值处理,然后找到轮廓。

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]

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

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

下一个 (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.

于 2012-05-18T05:29:27.537 回答
9

您可以使用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]]

最终看起来像这样: 在此处输入图像描述

注意:原始图像可能不需要排序,但使用压缩图像会导致在使用低阈值时出现一些压缩伪影,这就是我对排序进行后处理的原因。

希望有帮助!

于 2012-05-17T18:09:42.397 回答
0

您可以使用活动轮廓(气球/蛇)来准确选择黑色区域。可以在此处找到演示。OpenCV 中提供了活动轮廓,请检查cvSnakeImage

于 2012-05-17T15:23:12.970 回答