简体   繁体   English

如何在Python中使用OpenCV裁剪图像的黑色背景?

[英]How do I crop the black background of the image using OpenCV in Python?

So I have an image processing task at hand which requires me to crop a certain portion of an image. 因此,我手头有一个图像处理任务,需要我裁剪图像的特定部分。 I have no prior experience of OpenCV. 我没有OpenCV的经验。 I would like to know of a certain approach where I should be headed. 我想知道我应该去的某种方法。

Sample Input Image: 样本输入图像: 在此处输入图片说明

Sample Output Image: 样本输出图像: 在此处输入图片说明

What I initially thought was to convert the image to a bitmap and remove pixels that are below or above a certain threshold. 我最初的想法是将图像转换为位图,并删除低于或高于特定阈值的像素。 Since I am free to use OpenCV and Python, I would like to know of any automated algorithm that does so and if not, what should be the right approach for such a problem. 由于我可以自由使用OpenCV和Python,因此我想知道任何可以使用OpenCV和Python的自动化算法,如果没有,那么应该采用哪种正确的方法来解决此问题。 Thank you. 谢谢。

Applying a simple threshold should get rid of the background, provided it's always darker than the foreground. 如果背景色总是比前景色暗,则应用简单的阈值应摆脱背景色。 If you use the Otsu thresholding algorithm, it should choose a good partition for you. 如果您使用Otsu阈值算法,则应为您选择一个合适的分区。 Using your example as input, this gives: 使用您的示例作为输入,可以得出:

大津阈值图像

Next you could compute the bounding box to select the region of the foreground. 接下来,您可以计算边界框以选择前景区域。 Provided the background is distinct enough and there are no holes, this gives you the resulting rect: 如果背景足够清晰且没有孔洞,则可以得到以下结果:

[619 x 96 from (0, 113)]

You can then use this rect to crop the original, to produce the desired result: 然后,您可以使用此矩形裁剪原始图像,以产生所需的结果:

裁剪原版

I wrote the code to solve this in C++. 我用C ++编写了代码来解决这个问题。 A rough translation into Python would look something like this: 粗略翻译成Python看起来像这样:

import cv2 as cv

img = cv.imread(sys.argv[1])

grayscale = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

thresholded = cv.threshold(grayscale, 0, 255, cv.THRESH_OTSU)

imwrite("otsu.png", thresholded)

bbox = cv.boundingRect(thresholded)

x, y, w, h = bbox

print(bbox)

foreground = img[y:y+h, x:x+w]

imwrite("foreground.png", foreground)

This method is fast and simple. 这种方法既快速又简单。 If you find you have some white holes in your background which enlarge the bounding box, try applying an erosion operator. 如果发现背景中有一些白色的洞会扩大边界框,请尝试应用腐蚀算子。

FWIW I very much doubt you would get results like this as predictably or reliably using NNs. FWIW我非常怀疑您使用NN能否获得可预测或可靠的结果。

The thresholding seems like a good approach. 阈值似乎是一个好方法。 An overkill would be a neural network but you probably don't have enough data to train (:D) anyways check out this link. 过度的杀手可能是神经网络,但您可能没有足够的数据来训练(:D),总之要检查此链接。

you should be able to do something like: 您应该能够执行以下操作:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('img.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU

NN would be a overkill! NN会太过分了! You can do edge detection and get the extreme horizontal lines as boundaries. 您可以进行边缘检测,并获得极限水平线作为边界。 Then crop only the roi within these two lines. 然后仅在这两个行中裁剪roi。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM