如何从一本书的一页中提取一堆图像?

How do I extract a bunch of images from a page of a book?

我目前正在尝试从一本书的一堆页面中构建数据集。我想将页面中的蝴蝶提取到它们自己的图像中。

示例,

我已经进行了大量的谷歌搜索,只找到了模板匹配,但这似乎只适用于相同类型的图像。另外,由于背景非常稀疏,页面上真的没有其他东西,我想我可以使用它。我认为生成的图像必须重叠,但我最终还需要删除重叠并将图像居中,但我认为我可以做到。

有没有办法把蝴蝶放在第一位?

我没有按照评论中的建议使用阈值法,而是使用 Canny 边缘检测来寻找蝴蝶,因为其中一些蝴蝶的翅膀上靠近边缘有斑点,并且颜色与书本背景相同,这可能导致整个机翼出现问题。另外,由于图像很大,边缘检测在这里似乎很可靠。

方法本身非常简单(我使用 Python 和 OpenCV 来实现):

  1. 图像中的Canny边缘检测(手动设置参数)。
  2. 寻找等高线;排除小轮廓;绘制剩余轮廓以创建二元掩码。
  3. 迭代剩余轮廓;获取边界矩形;获取图像和蒙版的裁剪部分; "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
------------------