如何定位并测量图像中的长条形结构?求第三步后的优化方案
图像长条形结构检测:旋转后的后续处理方案
你已经完成图像二值化、轮廓检测和水平旋转,接下来可通过以下步骤精准提取目标长条形结构:
步骤1:裁剪旋转图像,去除无效黑边
旋转后图像周围会产生大量黑边,裁剪到目标物体的 bounding box 可减少干扰,聚焦有效区域:
# 获取旋转后轮廓的边界框 x2, y2, w2, h2 = cv2.boundingRect(cnt2) # 裁剪旋转后的二值图 cropped_binary = binary_rotated[y2:y2+h2, x2:x2+w2]
步骤2:形态学操作,强化长条形特征
使用开运算(先腐蚀再膨胀)去除小噪点,同时保留长条形的连续结构;若目标结构较细,可搭配水平方向结构元素做膨胀,突出横向特征:
# 创建适配长条形的水平结构元素 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 3)) # 开运算去噪并强化结构 morph_img = cv2.morphologyEx(cropped_binary, cv2.MORPH_OPEN, kernel)
步骤3:二次轮廓检测+筛选长条形轮廓
重新检测轮廓后,通过宽高比(水平旋转后长条形宽远大于高)和面积阈值筛选目标结构:
contours3, hierarchy3 = cv2.findContours(morph_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) target_contours = [] for cnt in contours3: area = cv2.contourArea(cnt) x, y, w, h = cv2.boundingRect(cnt) # 根据实际场景调整宽高比和面积阈值 if w / h > 5 and area > 100: target_contours.append(cnt)
步骤4:绘制并可视化结果
将筛选出的长条形轮廓绘制到原图和处理后的图像上:
# 在裁剪图上绘制目标轮廓 cv2.drawContours(cropped_binary, target_contours, -1, (0, 255, 0), 2) # 将裁剪结果放回旋转图(用于整体可视化) binary_rotated[y2:y2+h2, x2:x2+w2] = cropped_binary # 把轮廓坐标映射回原图并绘制 for cnt in target_contours: cnt_rotated = cnt + np.array([x2, y2]) cnt_original = cv2.transform(np.array([cnt_rotated]), rotate_matrix)[0] cv2.drawContours(img00, [cnt_original.astype(np.int32)], -1, (0, 0, 255), 2)
修改后的完整代码
import cv2 import numpy as np import math iterations = 7 a = 0 # 替换为你的实际变量值 img00 = cv2.imread('./camera1'+str(a)+'.jpg') gray00 = cv2.cvtColor(img00, cv2.COLOR_BGR2GRAY) median_blur1 = cv2.medianBlur(gray00, iterations) # 中值滤波去噪 ret1, thresh1 = cv2.threshold(median_blur1,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) # Otsu二值化 # 检测外部轮廓 contours1, hierarchy1 = cv2.findContours(thresh1.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if len(contours1) == 0: cv2.waitKey(0) cv2.destroyAllWindows() exit() # 获取最大轮廓 c1 = max(contours1, key = cv2.contourArea) height, width = img00.shape[:2] center = (width//2, height//2) # 用整数避免浮点问题 rect1 = cv2.minAreaRect(c1) print(rect1[2]) # 旋转图像到水平 rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=rect1[2], scale=1) binary_rotated = cv2.warpAffine(src=thresh1, M=rotate_matrix, dsize=(width, height)) # 检测旋转后的轮廓 contours2, hierarchy2 = cv2.findContours(binary_rotated.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnt2 = contours2[0] # 裁剪旋转图像,去除黑边 x2, y2, w2, h2 = cv2.boundingRect(cnt2) cropped_binary = binary_rotated[y2:y2+h2, x2:x2+w2] # 形态学操作强化长条形结构 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 3)) morph_img = cv2.morphologyEx(cropped_binary, cv2.MORPH_OPEN, kernel) # 筛选长条形轮廓 contours3, hierarchy3 = cv2.findContours(morph_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) target_contours = [] for cnt in contours3: area = cv2.contourArea(cnt) x, y, w, h = cv2.boundingRect(cnt) # 根据实际情况调整阈值 if (w / h > 5 or h / w > 5) and area > 100: target_contours.append(cnt) # 绘制结果 cv2.drawContours(cropped_binary, target_contours, -1, (0, 255, 0), 2) binary_rotated[y2:y2+h2, x2:x2+w2] = cropped_binary # 映射回原图并绘制 for cnt in target_contours: cnt_rotated = cnt + np.array([x2, y2]) cnt_original = cv2.transform(np.array([cnt_rotated]), rotate_matrix)[0] cv2.drawContours(img00, [cnt_original.astype(np.int32)], -1, (0, 0, 255), 2) cv2.imshow('Original Image with Target', img00) cv2.imshow('Rotated & Processed', binary_rotated) cv2.waitKey(0) cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者Kimwaga Makono
相关产品推荐
相关产品推荐

