python-3.x - 有什么方法可以找到多个图像的边界并单独裁剪它们?
问题描述
有什么方法可以找到多个图像的边界并单独裁剪它们。当可以在矩形框中对称地裁剪单个图像时,我可以裁剪它们,但是当要裁剪的图像不对称时变得具有挑战性。附图中有两个图像,即“细节B”和“细节C”。我只是想将它们裁剪成两个单独的图像。谁能建议如何使用 Python 获取这些图像?
解决方案
一般的方法很简单:
- 逆二进制阈值图像的灰度版本,例如使用 Otsu 的方法。既然你有全白背景,这应该没问题。
- 为了“合并”所有相邻部分,即“细节”本身、线条和标题,从阈值处理中扩展得到的掩码。
- 查找所有外部轮廓,过滤最大的轮廓,然后一个接一个:在单独的蒙版上绘制填充轮廓,并设置原始图像(蒙版为白色)和全白图像(其中蒙版为白色)的线性组合面具是黑色的;通过找到轮廓的边界矩形来裁剪正确的部分。
下面是一些使用 OpenCV 和 NumPy 的 Python 代码:
import cv2
import numpy as np
from skimage import io # Only needed for web grabbing images
# Read image from web
image = cv2.cvtColor(io.imread('https://i.stack.imgur.com/rq12v.jpg'), cv2.COLOR_RGB2BGR)
# Inverse binary threshold grayscale version of image using Otsu's
thres = cv2.threshold(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Dilate to merge all neighbouring parts
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
thres = cv2.dilate(thres, kernel)
# Find external contours with respect to OpenCV version
cnts = cv2.findContours(thres, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
# Iterate all contours...
area_thr = 10000
k = 0
for c in cnts:
# Filter large contours
if cv2.contourArea(c) > area_thr:
k = k + 1
# Get bounding rectangle of contour
rect = cv2.boundingRect(c)
x1 = rect[0]
y1 = rect[1]
x2 = x1 + rect[2]
y2 = y1 + rect[3]
# Generate filled contour mask
mask = np.zeros((thres.shape[0], thres.shape[1], 3), np.uint8)
mask = cv2.drawContours(mask, [c], -1, (1, 1, 1), cv2.FILLED)
# Generate and save cropped image
crop = 255 * np.ones((thres.shape[0], thres.shape[1], 3), np.uint8)
crop = (1 - mask) * crop + mask * image
crop = crop[y1:y2, x1:x2]
cv2.imwrite('crop' + str(k) + '.png', crop)
阈值化和膨胀后的初始掩码如下所示:
我们看到六个部分,而两个“细节”要大得多。
两个裁剪的“细节”是:
希望有帮助!
------------------
System information
------------------
Python: 3.8.1
NumPy: 1.18.1
OpenCV: 4.1.2
------------------
推荐阅读
- php - 如何将 PHP 变量插入 SQL 查询
- android-fragmentactivity - 我似乎无法访问覆盖方法中的值(自定义侦听器)
- javascript - 在javascript中导入函数
- r - 在 R 中使用 saveRDS() 时出现 NullPointerException
- java - Java struts recaptcha v2 无法正常工作
- ios - 为什么 md-select-on-focus 在 ios 中不起作用?
- javascript - amcharts中的图表容器宽度和高度动态
- unit-testing - 如何获得一个可以抛出我正在使用 XCTAssertNoThrow(...) 测试的函数的返回值
- vue.js - 带有 Laravel 5.5 的 Vue 单文件组件
- python - Kafka生产者flush和poll的区别