如何从图像中删除黑色部分?

dee*_*k_k 11 c++ opencv image-processing image-stitching

我使用OpenCV函数和C++将两个图像拼接在一起.现在我遇到的问题是最终图像包含一个大的黑色部分.

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

在此输入图像描述

如何删除黑色部分?

Abi*_*n K 19

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)
Run Code Online (Sandbox Code Playgroud)

现在找到最大的轮廓,这是你的形象.这是为了避免噪音,如果有的话(很可能没有).或者你可以使用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
Run Code Online (Sandbox Code Playgroud)

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

approx = cv2.approxPolyDP(best_cnt,0.01*cv2.arcLength(best_cnt,True),True)
Run Code Online (Sandbox Code Playgroud)

现在我们找到了角落.

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

far = approx[np.product(approx,2).argmax()][0]
Run Code Online (Sandbox Code Playgroud)

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

ymax = approx[approx[:,:,0]==1].max()
Run Code Online (Sandbox Code Playgroud)

下一步(x1,1).这是第二个元素为1的点,然后第一个元素是最大值.

xmax = approx[approx[:,:,1]==1].max()
Run Code Online (Sandbox Code Playgroud)

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

x = min(far[0],xmax)
y = min(far[1],ymax)
Run Code Online (Sandbox Code Playgroud)

如果使用(1,1)和(x,y)绘制矩形,则得到如下结果:

在此输入图像描述

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

img2 = img[:y,:x].copy()
Run Code Online (Sandbox Code Playgroud)

结果如下:

在此输入图像描述

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


mev*_*ron 9

您可以使用threshold,findContoursboundingRect执行此操作.

所以,这是一个使用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]]
Run Code Online (Sandbox Code Playgroud)

结尾看起来像这样: 在此输入图像描述

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

希望有所帮助!