【问题标题】:How to remove black part from the image?如何去除图像中的黑色部分?
【发布时间】:2012-05-17 09:00:18
【问题描述】:

我使用 OpenCV 函数和 C++ 将两个图像拼接在一起。现在我面临一个问题,即最终图像包含很大的黑色部分。

最终的图像应该是一个包含有效部分的矩形。 我的图片如下:

如何去除黑色部分?

【问题讨论】:

  • 您可能会使用 cvFindContours 来获取图像内容的范围,然后裁剪到那个范围......
  • 添加有问题的图片时,使用imwrite输出结果并添加。这比添加屏幕截图要好,因为回答您问题的人需要从图像中删除不需要的区域。
  • 你的工作空间有点整洁。
  • 您希望如何去除黑色部分?新图的左上角和现在一样,右下角在拼接图的最下方,这样可以吗?您是否要剪切它,使其包含最少数量的黑色部分,同时仍包含所有图像部分,反之亦然,以便在删除所有黑色部分的同时剪切掉最少数量的图像部分?请详细说明:)

标签: c++ image-processing opencv image-stitching


【解决方案1】:

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]

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

【讨论】:

  • :由于我更熟悉 C++ 并尝试将代码(在 python 中)转换为 C++,但未能成功。如果您可以分享相同的 C++ 语言代码,我会非常感谢。
  • 对不起,我不擅长 C++。但是,如果您告诉我您对我方法中的任何步骤有任何疑问,我可以用更简单的方式进行解释。
  • :我已经完成了所有步骤,直到 approxpolyDP,但我不知道如何计算 C 中坐标点的乘积,我想你也使用了伪代码。你能告诉我如何计算C 中坐标点的乘积,或者给我任何有人在 C 中使用过您的方法类型的链接。作为参考,我在应用 approxpoly() 方法后的图像是 [i.imgur.com/Qfoyt.jpg?1]。希望您在应用 approxpolyDp 后也得到相同的输出图像()。
  • 我的代码是opencv python api中的工作代码。实际上,我得到了 4 个坐标的列表,例如 approx = [[a,b],[c,d],[e,f],[g,h],[i,j]]。现在我将每个集合乘以它们的值并将其存储在另一个数组中。比如for i in approx: k[0]=i[0]*i[1]。现在在结果数组中取最大值的参数。这是我在 numpy 的帮助下一步完成的,一个 python 库:far = approx[np.product(approx,2).argmax()][0]
  • 好的。但是,我认为在 C 中,我们不能这样取坐标。你能告诉我其他方法吗。我在 SO 中看到 Hough 变换用于获取线条,但我认为这会不必要地增加复杂性。你知道其他方法吗?
【解决方案2】:

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

最终看起来像这样:

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

希望有帮助!

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 你能告诉我如何实现它来去除黑色部分吗?
    • 你添加的链接都失效了。最好展示和解释一个实现,这样你的答案是永恒的。
    猜你喜欢
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多