如何从一本书的一页中提取一堆图像?
How do I extract a bunch of images from a page of a book?
我目前正在尝试从一本书的一堆页面中构建数据集。我想将页面中的蝴蝶提取到它们自己的图像中。
示例,
我已经进行了大量的谷歌搜索,只找到了模板匹配,但这似乎只适用于相同类型的图像。另外,由于背景非常稀疏,页面上真的没有其他东西,我想我可以使用它。我认为生成的图像必须重叠,但我最终还需要删除重叠并将图像居中,但我认为我可以做到。
有没有办法把蝴蝶放在第一位?
我没有按照评论中的建议使用阈值法,而是使用 Canny 边缘检测来寻找蝴蝶,因为其中一些蝴蝶的翅膀上靠近边缘有斑点,并且颜色与书本背景相同,这可能导致整个机翼出现问题。另外,由于图像很大,边缘检测在这里似乎很可靠。
方法本身非常简单(我使用 Python 和 OpenCV 来实现):
- 图像中的Canny边缘检测(手动设置参数)。
- 寻找等高线;排除小轮廓;绘制剩余轮廓以创建二元掩码。
- 迭代剩余轮廓;获取边界矩形;获取图像和蒙版的裁剪部分; "clean" 通过去除相邻蝴蝶的潜在部分来掩蔽;创建具有透明背景的新(裁剪)图像。
完整代码如下:
import cv2
import numpy as np
import platform # Only needed for system information
from skimage import io # Only needed for image web grabbing
# Read image from web; enforce BGR color ordering
image = cv2.cvtColor(io.imread('https://i.stack.imgur.com/bwS3g.jpg'),
cv2.COLOR_RGB2BGR)
# Canny edge detection
canny = cv2.Canny(image, 50, 150)
canny = cv2.morphologyEx(canny, cv2.MORPH_CLOSE,
cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))
# Find contours; use proper return value with respect to OpenCV version
cnts = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
# Filter contours with sufficient areas; create binary mask from them
cnts = [c for c in cnts if cv2.contourArea(c) > 10000]
mask = np.zeros_like(canny)
mask = cv2.drawContours(mask, np.array(cnts), -1, 255, cv2.FILLED)
# Iterate all contours...
for i, c in enumerate(cnts):
# Get bounding rectangle of contour and min/max coordinates
rect = cv2.boundingRect(c)
(x1, y1) = rect[:2]
x2 = x1 + rect[2]
y2 = y1 + rect[3]
# Get image section
crop_image = image[y1:y2, x1:x2]
# Get mask section and cut possible neighbouring contours
crop_mask = mask[y1:y2, x1:x2].copy()
cnts = cv2.findContours(crop_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
c = max(cnts, key=cv2.contourArea)
crop_mask[:, :] = 0
cv2.drawContours(crop_mask, [c], -1, 255, cv2.FILLED)
# Create butterfly image with transparent background
butterfly = np.zeros((rect[3], rect[2], 4), np.uint8)
butterfly[:, :, :3] = cv2.bitwise_and(crop_image, crop_image,
mask=crop_mask)
butterfly[:, :, 3] = crop_mask
cv2.imwrite(str(i) + '.png', butterfly)
print('------------------')
print('System information')
print('------------------')
print('Python: ', platform.python_version())
print('NumPy: ', np.__version__)
print('OpenCV: ', cv2.__version__)
print('------------------')
这是保存的两张蝴蝶图片。
您可以稍微模糊 alpha 通道以获得从蝴蝶到背景的更平滑过渡。
希望对您有所帮助!
------------------
System information
------------------
Python: 3.7.1
NumPy: 1.18.1
OpenCV: 4.1.2
------------------
我目前正在尝试从一本书的一堆页面中构建数据集。我想将页面中的蝴蝶提取到它们自己的图像中。
示例,
我已经进行了大量的谷歌搜索,只找到了模板匹配,但这似乎只适用于相同类型的图像。另外,由于背景非常稀疏,页面上真的没有其他东西,我想我可以使用它。我认为生成的图像必须重叠,但我最终还需要删除重叠并将图像居中,但我认为我可以做到。
有没有办法把蝴蝶放在第一位?
我没有按照评论中的建议使用阈值法,而是使用 Canny 边缘检测来寻找蝴蝶,因为其中一些蝴蝶的翅膀上靠近边缘有斑点,并且颜色与书本背景相同,这可能导致整个机翼出现问题。另外,由于图像很大,边缘检测在这里似乎很可靠。
方法本身非常简单(我使用 Python 和 OpenCV 来实现):
- 图像中的Canny边缘检测(手动设置参数)。
- 寻找等高线;排除小轮廓;绘制剩余轮廓以创建二元掩码。
- 迭代剩余轮廓;获取边界矩形;获取图像和蒙版的裁剪部分; "clean" 通过去除相邻蝴蝶的潜在部分来掩蔽;创建具有透明背景的新(裁剪)图像。
完整代码如下:
import cv2
import numpy as np
import platform # Only needed for system information
from skimage import io # Only needed for image web grabbing
# Read image from web; enforce BGR color ordering
image = cv2.cvtColor(io.imread('https://i.stack.imgur.com/bwS3g.jpg'),
cv2.COLOR_RGB2BGR)
# Canny edge detection
canny = cv2.Canny(image, 50, 150)
canny = cv2.morphologyEx(canny, cv2.MORPH_CLOSE,
cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))
# Find contours; use proper return value with respect to OpenCV version
cnts = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
# Filter contours with sufficient areas; create binary mask from them
cnts = [c for c in cnts if cv2.contourArea(c) > 10000]
mask = np.zeros_like(canny)
mask = cv2.drawContours(mask, np.array(cnts), -1, 255, cv2.FILLED)
# Iterate all contours...
for i, c in enumerate(cnts):
# Get bounding rectangle of contour and min/max coordinates
rect = cv2.boundingRect(c)
(x1, y1) = rect[:2]
x2 = x1 + rect[2]
y2 = y1 + rect[3]
# Get image section
crop_image = image[y1:y2, x1:x2]
# Get mask section and cut possible neighbouring contours
crop_mask = mask[y1:y2, x1:x2].copy()
cnts = cv2.findContours(crop_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
c = max(cnts, key=cv2.contourArea)
crop_mask[:, :] = 0
cv2.drawContours(crop_mask, [c], -1, 255, cv2.FILLED)
# Create butterfly image with transparent background
butterfly = np.zeros((rect[3], rect[2], 4), np.uint8)
butterfly[:, :, :3] = cv2.bitwise_and(crop_image, crop_image,
mask=crop_mask)
butterfly[:, :, 3] = crop_mask
cv2.imwrite(str(i) + '.png', butterfly)
print('------------------')
print('System information')
print('------------------')
print('Python: ', platform.python_version())
print('NumPy: ', np.__version__)
print('OpenCV: ', cv2.__version__)
print('------------------')
这是保存的两张蝴蝶图片。
您可以稍微模糊 alpha 通道以获得从蝴蝶到背景的更平滑过渡。
希望对您有所帮助!
------------------
System information
------------------
Python: 3.7.1
NumPy: 1.18.1
OpenCV: 4.1.2
------------------