【问题标题】:How to use OpenCV to crop an image based on a certain criteria?如何使用 OpenCV 根据特定标准裁剪图像?
【发布时间】:2020-04-16 07:34:51
【问题描述】:

我想使用 python 的 OpenCV 库裁剪如下图所示的图像。感兴趣的区域位于顶部和底部的波浪线以及侧面的线内。问题是每个图像都略有不同。这意味着我需要一些自动裁剪感兴趣区域的方法。我猜顶部和侧面会很容易,因为您可以将其裁剪 10 像素左右。但是我怎样才能裁剪出线条不直的图像的下半部分呢?我已包含此示例图像。下面的图像以粉红色突出显示我有兴趣保留的图像区域。

【问题讨论】:

  • 欢迎来到 StackOverflow。本网站不作为一般问题解决门户。社区将与您一起获得可行的解决方案,但您应该分享一些代码,以显示您已经完成和未完成的工作。阅读如何创建一个最小的、可重现的示例 (stackoverflow.com/help/minimal-reproducible-example) 和我如何提出一个好问题 (stackoverflow.com/help/how-to-ask)?我建议您查看粉红色区域的洪水填充和轮廓。
  • 您好 - 我已经尝试使用我自己的基本代码,但它只是无法正常工作。我尝试了以下方法: img = img[30:-30, 30:-30, :] 但它只从图像的每一端刮掉 30 个像素。我正在寻找一种更复杂的方法来删除图像的底部轮廓。
  • 我建议您查看 cv2.floodfill 和 cv2.findContours 以获得粉红色区域的外部轮廓。为该区域创建一个蒙版,并将该区域复制到一个新的黑色图像中,该图像与该轮廓的边界框大小相同。

标签: python opencv image-processing crop


【解决方案1】:

这是使用 Python/OpenCV 的一种方法。

  • 读取输入
  • 获取中心点(假设它在所需区域内)
  • 将图像转换为灰度
  • 填充灰色图像并将背景设置为黑色
  • 获取最大轮廓及其边界框
  • 绘制黑色背景上填充的最大轮廓作为蒙版
  • 将蒙版应用于输入图像
  • 裁剪蒙版的输入图像

输入:

import cv2
import numpy as np

# load image and get dimensions
img = cv2.imread("odd_region.png")
hh, ww, cc = img.shape

# compute center of image (as integer)
wc = ww//2
hc = hh//2

# create grayscale copy of input as basis of mask
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# create zeros mask 2 pixels larger in each dimension
zeros = np.zeros([hh + 2, ww + 2], np.uint8)

# do floodfill at center of image as seed point
ffimg = cv2.floodFill(gray, zeros, (wc,hc), (255), (0), (0), flags=8)[1]

# set rest of ffimg to black
ffimg[ffimg!=255] = 0

# get contours, find largest and its bounding box 
contours = cv2.findContours(ffimg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
area_thresh = 0
for cntr in contours:
    area = cv2.contourArea(cntr)
    if area > area_thresh:
        area = area_thresh
        outer_contour = cntr
        x,y,w,h = cv2.boundingRect(outer_contour)

# draw the filled contour on a black image
mask = np.full([hh,ww,cc], (0,0,0), np.uint8)
cv2.drawContours(mask,[outer_contour],0,(255,255,255),thickness=cv2.FILLED)

# mask the input
masked_img = img.copy()
masked_img[mask == 0] = 0
#masked_img[mask != 0] = img[mask != 0]

# crop the bounding box region of the masked img
result = masked_img[y:y+h, x:x+w]

# draw the contour outline on a copy of result
result_outline = result.copy()
cv2.drawContours(result_outline,[outer_contour],0,(0,0,255),thickness=1,offset=(-x,-y))


# display it
cv2.imshow("img", img)
cv2.imshow("ffimg", ffimg)
cv2.imshow("mask", mask)
cv2.imshow("masked_img", masked_img)
cv2.imshow("result", result)
cv2.imshow("result_outline", result_outline)
cv2.waitKey(0)
cv2.destroyAllWindows()

# write result to disk
cv2.imwrite("odd_region_cropped.png", result)
cv2.imwrite("odd_region_cropped_outline.png", result_outline)


结果:

绘制轮廓的结果:

【讨论】:

    猜你喜欢
    • 2020-05-17
    • 2022-07-24
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    相关资源
    最近更新 更多