Opencv 学习笔记:指定路径上亮暗像素交界点检测(鼠标交互版)

在图像分析场景中,常需检测自定义路径上最亮 / 最暗像素的交界点(如手绘直线、曲线边缘)。本文结合「鼠标交互绘制路径」+「路径像素遍历」+「亮暗交界检测」,实现指定路径的精准边缘定位,新手可直接复用完整流程。

核心代码实现

python 复制代码
import cv2 as cv
import numpy as np

# 全局变量:存储路径坐标、图像等关键数据
x1, y1 = -1, -1  # 鼠标按下初始坐标
path_y = []      # 路径y坐标列表
path_x = []      # 路径x坐标列表
binary_bg = None # 背景二值化图
src = None       # 原始图像

# 鼠标回调函数:绘制路径+提取路径像素坐标
def on_mouse_action(event, x, y, flags, param):
    global x1, y1, path_y, path_x, binary_bg, src, outimage
    
    if event == cv.EVENT_LBUTTONDOWN:
        # 左键按下:记录初始坐标
        x1, y1 = x, y
        print(f"左键点击:({x1}, {y1})")
        
    elif event == cv.EVENT_MOUSEMOVE and flags == cv.EVENT_FLAG_LBUTTON:
        # 左键拖拽:实时绘制路径(可选,增强交互性)
        cv.line(outimage, (x1, y1), (x, y), (255, 0, 0), 2)
        x1, y1 = x, y
        
    elif event == cv.EVENT_LBUTTONUP:
        # 左键松开:绘制最终路径 + 提取路径像素坐标
        print(f"鼠标松开:终点({x}, {y})")
        cv.line(outimage, (x1, y1), (x, y), (255, 0, 0), 2)
        cv.line(src, (x1, y1), (x, y), (255, 0, 0), 2)
        
        # 1. 路径区域二值化(提取手绘路径像素)
        out_gray = cv.cvtColor(outimage, cv.COLOR_BGR2GRAY)
        ret, binary_path = cv.threshold(out_gray, 20, 255, cv.THRESH_BINARY)
        
        # 2. 遍历图像,提取路径上的所有像素坐标
        path_y.clear()  # 清空历史坐标,避免累积
        path_x.clear()
        for i in range(src.shape[0]):
            for j in range(src.shape[1]):
                if binary_path[i, j] == 255:  # 路径像素(白色)
                    path_y.append(i)
                    path_x.append(j)
        
        print(f"提取到路径像素数量:{len(path_x)}")

# ===================== 主程序 =====================
if __name__ == "__main__":
    # 1. 读取图像并初始化
    src = cv.imread("./image/15.bmp")
    if src is None:
        print("图像读取失败,请检查路径!")
        exit()
    
    # 初始化路径画布(纯黑,用于绘制手绘路径)
    outimage = np.zeros_like(src)
    # 背景图像二值化(用于检测亮暗交界)
    src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    ret, binary_bg = cv.threshold(src_gray, 20, 255, cv.THRESH_BINARY)
    
    # 2. 创建窗口并绑定鼠标回调
    cv.namedWindow('src', cv.WINDOW_NORMAL)
    cv.resizeWindow('src', 600, 600)
    cv.setMouseCallback('src', on_mouse_action)
    
    # 3. 主循环:实时检测路径上的亮暗交界点
    while True:
        # 显示图像
        cv.imshow('src', src)
        cv.imshow('path_canvas', outimage)
        
        # 检测路径上的亮暗交界点(路径像素数≥2才执行)
        if len(path_x) >= 2:
            for v in range(len(path_x)-1):
                # 获取路径上相邻两个像素的坐标
                y_curr, x_curr = path_y[v], path_x[v]
                y_next, x_next = path_y[v+1], path_x[v+1]
                
                # 计算像素值差值(255=白→黑交界,-255=黑→白交界)
                pix_diff = binary_bg[y_curr, x_curr] - binary_bg[y_next, x_next]
                
                # 检测到亮暗交界,用绿色实心圆标注
                if pix_diff == 255:
                    cv.circle(src, (x_curr, y_curr), 5, (0, 255, 0), -1)
        
        # 按q退出程序
        if cv.waitKeyEx(1) == ord('q'):
            break
    
    cv.destroyAllWindows()

关键知识点解析

1. 核心流程拆解

表格

步骤 核心操作 作用说明
鼠标交互 cv.setMouseCallback() 捕获左键按下 / 拖拽 / 松开事件,绘制自定义路径
路径提取 二值化 + 像素遍历 将手绘路径转为白色像素,提取所有路径像素坐标
交界检测 相邻像素差值计算 binary_bg[y,x] - binary_bg[y+1,x+1] == 255 判定白→黑交界
可视化标注 cv.circle() 绿色实心圆标注交界点,直观展示检测结果

2. 原代码核心修复与优化

  • 全局变量管理 :规范定义全局变量,清空历史路径坐标(path_y.clear()),避免多次绘制路径导致坐标累积;
  • 索引越界防护 :新增len(path_x)>=2判断,避免路径像素不足时遍历报错;
  • 数据结构简化 :移除冗余的None列表,直接用空列表存储路径坐标,提升效率;
  • 变量初始化binarys改为np.zeros_like(src),适配图像维度,避免通道数错误;
  • 鼠标事件修正flags == cv.EVENT_LBUTTONDOWN改为cv.EVENT_FLAG_LBUTTON(正确的左键按住标志位)。

3. 核心参数说明

  • 二值化阈值 20:适配手绘路径的蓝色线条(值 > 20 判定为路径像素),可根据路径颜色调整;
  • 交界判定值 255:二值化后像素值只有 0(黑)/255(白),差值 255 表示当前像素白、下一个像素黑;
  • 实心圆标注cv.circle(..., -1)填充圆形,交界点更醒目,便于视觉识别。

4. 适用场景

  • 工业视觉:检测零件指定路径上的明暗边缘、缺陷位置;
  • 图像分析:定位自定义线条上的亮度突变点(如光谱图、波形图边缘);
  • 交互标注:手动绘制路径后,自动检测路径上的关键边缘点。

总结

  1. 指定路径亮暗交界检测的核心是「鼠标绘制路径→提取路径像素→相邻像素差值计算」;
  2. 需重点处理全局变量清空索引越界防护,避免多次交互导致的数据错误;
  3. 二值化阈值和交界判定值是核心参数,需根据图像亮度、路径颜色适配调整。
相关推荐
时代的凡人6 小时前
0208晨间笔记
笔记
今天只学一颗糖6 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
testpassportcn7 小时前
AWS DOP-C02 認證完整解析|AWS DevOps Engineer Professional 考試
网络·学习·改行学it
游乐码10 小时前
c#变长关键字和参数默认值
学习·c#
饭碗、碗碗香11 小时前
【Python学习笔记】:Python的hashlib算法简明指南:选型、场景与示例
笔记·python·学习
Wils0nEdwards11 小时前
初中化学1
笔记
魔力军12 小时前
Rust学习Day4: 所有权、引用和切片介绍
开发语言·学习·rust
wubba lubba dub dub75012 小时前
第三十六周 学习周报
学习
学编程的闹钟12 小时前
PHP字符串表示方式全解析
学习
Lbs_gemini060312 小时前
01-01-01 C++编程知识 C++入门 工具安装
c语言·开发语言·c++·学习·算法