如何将OpenCV识别的轮廓形状复制到空白画布(Python)
将OpenCV识别的轮廓形状精准复制到空白画布(非Bounding Box方案)
嘿,我完全懂你为啥不想用 bounding box 这类方案——之前我也试过,要么会把多余的空白区域带进来,要么没法完美贴合轮廓形状。既然你已经知道 OpenCV 图像本质就是 Numpy 数组,那咱们直接用掩码操作+坐标映射来搞定,精准复制蓝色轮廓到40×40的白色画布,完全贴合形状,没有多余部分。
核心思路
我们的目标是把原图像中填充为蓝色的轮廓区域,精准“抠”出来放到空白画布上。核心步骤是:
- 生成只包含该轮廓的掩码(相当于给形状打个专属标记)
- 通过掩码从原图像中提取出蓝色形状的像素
- 把提取到的形状映射到空白画布的合适位置(这里默认居中,你也可以改任意位置)
修改后的完整代码
把下面的代码替换你的原有代码,就能实现需求:
import numpy as np import cv2 # 创建40×40像素的白色画布 blank_image = np.zeros((40,40,3), np.uint8) blank_image.fill(255) # 读取图像并识别轮廓 im = cv2.imread('img.png') imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(imgray, 127, 255, 0) # 兼容OpenCV3和4的findContours返回值差异 try: _, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) except ValueError: contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnt = contours[4] # 在原图像上填充蓝色轮廓 cv2.drawContours(im, [cnt], 0, (255,0,0), -1) # -------------------------- 关键复制逻辑 -------------------------- # 1. 创建轮廓掩码:只保留cnt对应的区域 mask = np.zeros_like(imgray) cv2.drawContours(mask, [cnt], 0, 255, -1) # 2. 从原图像中提取蓝色形状区域 blue_shape = cv2.bitwise_and(im, im, mask=mask) # 3. 将形状映射到空白画布(这里选择居中放置) x, y, w, h = cv2.boundingRect(cnt) canvas_h, canvas_w = blank_image.shape[:2] # 计算形状在画布上的起始坐标,让形状居中 start_x = (canvas_w - w) // 2 start_y = (canvas_h - h) // 2 # 处理形状尺寸超出画布的情况,避免数组索引错误 end_x = min(start_x + w, canvas_w) end_y = min(start_y + h, canvas_h) crop_w = end_x - start_x crop_h = end_y - start_y # 裁剪原形状的有效区域,复制到空白画布 blank_image[start_y:end_y, start_x:end_x] = blue_shape[y:y+crop_h, x:x+crop_w] # ------------------------------------------------------------------- # 显示结果 cv2.imshow('原图像(带蓝色轮廓)', im) cv2.imshow('空白画布(已复制形状)', blank_image) cv2.waitKey(0) cv2.destroyAllWindows() # 打印轮廓坐标(你原有的需求) for a in cnt: print(a)
代码说明
- 掩码生成:
mask是一个和原图像灰度图同尺寸的单通道数组,只有轮廓区域是白色(255),其余都是黑色(0),这样就能精准定位我们要复制的形状。 - 提取形状:
cv2.bitwise_and操作会只保留掩码为白色区域的像素,也就是原图像中的蓝色轮廓部分,完全不会带多余区域。 - 坐标映射:通过计算轮廓的外接矩形尺寸,我们把形状放到空白画布的中心,同时处理了形状超出画布的情况,避免出现数组索引越界的错误。
这个方法完全基于 Numpy 数组的切片和位操作,没有使用你不想用的 bounding box 裁剪,而是精准复制轮廓的形状,完美贴合你的需求。
内容的提问来源于stack exchange,提问作者lucians
相关产品推荐
相关产品推荐

