cv2.bitwise_or 提取ROI区域

原图如下所示,想提取圆形ROI区域,红色框

img = np.ones(ori_img.shape, dtype="uint8")
img = img * 255
cv2.circle(img, (50,50), 50, 0, -1)
self.bitwiseOr = cv2.bitwise_or(ori_img, circle)

 使用一个和原图尺寸一致的图像做mask,图白圆黑

 

以上图像和原图做bitwish_or可获得如下图像,提取圆形ROI区域

 如果圆形ROI区域需要再次去除周围的黑边,可以用同样的方法,构造一个矩形mask

图白矩形黑

 在执行一次bitwish_or,可获取如下结果,通过这种方式可以获取不规则的ROI

import cv2 import numpy as np # 读取图像 img_path = '/home/incam/Desktop/mycode/template/CAD/cad/Snipaste_2025-09-09_16-38-23.png' image = cv2.imread(img_path) if image is None: print("图像加载失败,请检查路径") exit() #图像中有多个区域,各自有边框,此外还有一个大的框将这三个区域都包含在内,友好的是,大框内的三个小框之间各有一条分割线隔开,也就是说在大框上存在与分割线的交点,现在只能检测出整个的大框,可需要的是三个小框的坐标,针对这种情况应该怎么处理 roi = cv2.selectROI("Select ROI", image, showCrosshair=True, fromCenter=False) cv2.destroyWindow("Select ROI") (x, y, w, h) = roi if w == 0 or h == 0: imCrop = image else: imCrop = image[y:y+h, x:x+w] # 转换为 HSV 颜色空间 hsv = cv2.cvtColor(imCrop, cv2.COLOR_BGR2HSV) #白色部分内容转换为灰度图 gray = cv2.cvtColor(imCrop, cv2.COLOR_BGR2GRAY) ########################检测彩色区域############# # 检测红色 # 红色在 HSV 中有两个范围:低 H 和高 H(因为色环是环形) lower_red1 = np.array([0, 100, 100]) # 红色下界1 upper_red1 = np.array([10, 255, 255]) lower_red2 = np.array([170, 100, 100]) # 红色下界2 upper_red2 = np.array([180, 255, 255]) mask1 = cv2.inRange(hsv, lower_red1, upper_red1) mask2 = cv2.inRange(hsv, lower_red2, upper_red2) red_mask = cv2.bitwise_or(mask1, mask2) # 检测蓝色 lower_blue = np.array([100, 100, 100]) upper_blue = np.array([130, 255, 255]) blue_mask = cv2.inRange(hsv, lower_blue, upper_blue) # 检测绿色 lower_green = np.array([40, 100, 100]) upper_green = np.array([80, 255, 255]) green_mask = cv2.inRange(hsv, lower_green, upper_green) # 可视化各个颜色掩码 cv2.imshow("Red Mask", red_mask) cv2.imshow("Blue Mask", blue_mask) cv2.imshow("Green Mask", green_mask) # 合并所有颜色区域 color_mask = cv2.bitwise_or(cv2.bitwise_or(red_mask, blue_mask), green_mask) ##############检测白色区域########## # 白色:高亮度 + 低饱和度 lower_white = np.array([0, 0, 200]) # V > 200,接近白色 upper_white = np.array([180, 30, 255]) # S < 30,避免彩色干扰 mask_white = cv2.inRange(hsv, lower_white, upper_white) #结合灰度图增强白色检测效果 _, mask_white_gray = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY) mask_white = cv2.bitwise_or(mask_white, mask_white_gray) # 合并所有掩码(彩色 + 白色) combined_mask = cv2.bitwise_or(color_mask, mask_white) # 形态学操作去噪 # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) # combined_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_CLOSE, kernel) #连接断裂 # combined_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_OPEN, kernel) #去除噪点 # _, binary = cv2.threshold(combined_mask, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) _, binary = cv2.threshold(combined_mask, 127, 255, cv2.THRESH_BINARY) # 固定阈值二值化 #形态学操作,去除噪点,连接断裂区域 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) # 查找轮廓 # contours, _ = cv2.findContours(combined_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if not contours: print("未检测到任何轮廓") else: min_side_threshold = 150 # 3. 处理每个轮廓 for i, contour in enumerate(contours): # 获取当前轮廓点 contour_points = contour.reshape(-1, 2) if len(contour_points) >= 3: # 计算最小外接矩形 rect = cv2.minAreaRect(contour_points) width, height = rect[1] # 获取宽高 # 跳过过小的矩形(任一方向边长不足阈值) if min(width, height) < min_side_threshold: continue # 绘制最小外接矩形 # min_side_threshold = 400 # for i, cnt in enumerate(contours): # if cv2.contourArea(cnt) < min_side_threshold: # continue # 获取最小外接矩形 # rect = cv2.minAreaRect(cnt) box = cv2.boxPoints(rect) box = np.int32(box) # 扩展一点避免裁剪 expansion = 2 center, (w, h), angle = rect rect_expanded = (center, (w + 2*expansion, h + 2*expansion), angle) # 获取矩形角点并排序 # box = cv2.boxPoints(rect) box = cv2.boxPoints(rect_expanded) box = np.int32(box) box = sorted(box, key=lambda x: (x[0], x[1])) box = np.array([box[0], box[2], box[3], box[1]]) # 左上开始顺时针 # # 绘制矩形和编号 # color = (0, 255 - i*50, 100 + i*50) # 自动生成不同颜色 # # cv2.drawContours(image, [box], 0, color, 2) # cv2.drawContours(imCrop, [box], 0, color, 2) cv2.drawContours(imCrop, [box], 0, (0, 255, 0), 2) # cv2.putText(image, str(i+1), tuple(box[0]), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0,0,255), 2) # # 将框的坐标转换回原图坐标系 box[:, 0] += roi[0] # x坐标加上ROI的x偏移 box[:, 1] += roi[1] # y坐标加上ROI的y偏移 # 输出坐标信息,先输出i最大的那个,也就是从右下角开始输出 # print(f"\n区域 {i+1} 坐标:") print(f"Top-Left: {tuple(box[0])}, Top-Right: {tuple(box[1])}, Bottom-Right: {tuple(box[2])}, Bottom-Left: {tuple(box[3])}") # box = cv2.boxPoints(rect_expanded) # box = np.int32(box) # # 坐标偏移回全局图像 # box_global = box.copy() # box_global[:, 0] += x # box_global[:, 1] += y # cv2.drawContours(image, [box_global], 0, (0, 255, 0), 2) # cv2.putText(image, str(i+1), tuple(box_global[0]), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) # 显示结果 cv2.imshow("Original Image", image) cv2.imshow("Combined Mask", combined_mask) cv2.imshow("Segmented Result", imCrop) cv2.waitKey(0) cv2.destroyAllWindows() 在这段代码的基础上,实现:图像中有多个区域,各自有边框(称为小框),此外还有一个大的框将这三个区域都包含在内,友好的是,大框内的三个小框之间各有一条分割线隔开,也就是说在大框上存在与分割线的交点,现在只能检测出整个的大框,可我需要的是三个小框的坐标,这个功能
最新发布
10-10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值