在图像分析中,检测像素亮暗交界点(黑白边缘)、实现鼠标交互标注是基础实用技能。本文整合 “像素亮暗交界点定位” 和 “鼠标交互绘图” 两大功能,新手可快速掌握核心逻辑并直接复用。

核心代码实现

import cv2 as cv
import numpy as np

# ===================== 功能1:检测像素亮暗交界点 =====================
def detect_bright_dark_edge():
    # 1. 读取图像并校验
    src = cv.imread("./image/1.bmp")
    if src is None:
        print("图像读取失败,请检查路径!")
        return
    src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    
    # 2. 二值化:分离亮暗区域(阈值150可按需调整)
    ret, binary = cv.threshold(src_gray, 150, 255, cv.THRESH_BINARY)
    
    # 3. 检测指定行的亮暗交界点(y=100行,x范围200~500)
    check_row = 100  # 待检测行坐标
    x_start, x_end = 200, 500  # 待检测列范围
    
    # 绘制检测基准线(绿色,便于定位)
    cv.line(src, (x_start, check_row), (x_end, check_row), (0, 255, 0), 2)
    
    # 遍历列范围,检测亮暗交界
    for x in range(x_start, x_end):
        # 避免列索引越界(核心避坑点)
        if x + 1 >= src_gray.shape[1]:
            break
        # 获取当前像素和右侧像素值
        pix_current = binary[check_row, x]
        pix_next = binary[check_row, x+1]
        pix_diff = pix_current - pix_next
        
        # 检测到白→黑交界点,用蓝色实心圆标注
        if pix_diff == 255:
            cv.circle(src, (x, check_row), 5, (255, 0, 0), -1)
            print(f"亮暗交界点:({x}, {check_row})")
    
    # 显示检测结果
    cv.namedWindow('edge_detect', cv.WINDOW_NORMAL)
    cv.resizeWindow('edge_detect', 600, 600)
    cv.imshow('edge_detect', src)
    return src

# ===================== 功能2:鼠标交互绘图 =====================
def mouse_interaction_demo(img):
    # 全局变量存储鼠标按下的初始坐标
    global x1, y1
    x1, y1 = -1, -1
    
    # 鼠标回调函数:处理左键按下/拖拽/松开事件
    def on_mouse(event, x, y, flags, param):
        global x1, y1
        if event == cv.EVENT_LBUTTONDOWN:
            # 左键按下,记录初始坐标
            x1, y1 = x, y
            print(f"左键点击:({x1}, {y1})")
        elif event == cv.EVENT_MOUSEMOVE and flags == cv.EVENT_FLAG_LBUTTON:
            # 左键拖拽(实时打印状态)
            print(f"左键拖拽:当前({x}, {y})")
        elif event == cv.EVENT_LBUTTONUP:
            # 左键松开,绘制直线
            print(f"鼠标松开:终点({x}, {y})")
            cv.line(img, (x1, y1), (x, y), (255, 0, 0), 2)
    
    # 绑定鼠标回调并显示
    cv.namedWindow('mouse_demo', cv.WINDOW_NORMAL)
    cv.resizeWindow('mouse_demo', 600, 600)
    cv.setMouseCallback('mouse_demo', on_mouse)
    
    # 按q退出循环
    while True:
        cv.imshow('mouse_demo', img)
        if cv.waitKeyEx(1) == ord('q'):
            break

# ===================== 主程序执行 =====================
if __name__ == "__main__":
    edge_img = detect_bright_dark_edge()
    if edge_img is not None:
        mouse_interaction_demo(edge_img)
    cv.destroyAllWindows()

关键知识点解析

1. 亮暗交界点检测核心

表格

步骤核心逻辑避坑要点
二值化cv.threshold()将图像转为黑白,简化交界判断阈值需适配图像亮度,暗图调低、亮图调高
差值计算pix_current - pix_next255 = 白→黑交界,-255 = 黑→白交界
越界防护x+1 >= src_gray.shape[1]避免索引超出图像宽度导致报错
可视化cv.circle(..., -1)线宽 - 1 填充圆形,交界点更醒目

2. 鼠标交互核心

表格

事件类型触发条件核心操作
EVENT_LBUTTONDOWN左键按下记录初始坐标x1, y1
EVENT_MOUSEMOVE+EVENT_FLAG_LBUTTON左键拖拽实时获取拖拽坐标
EVENT_LBUTTONUP左键松开绘制从初始点到终点的直线

3. 原代码核心修复

  • 索引越界:新增x+1 >= src_gray.shape[1]判断,解决像素访问报错;
  • 鼠标事件错误:将flags == cv.EVENT_LBUTTONDOWN修正为cv.EVENT_FLAG_LBUTTON(左键按住标志位);
  • 全局变量:规范定义x1, y1全局变量,保证鼠标坐标跨事件传递;
  • 圆形填充:交界点标注改为实心圆(线宽 - 1),视觉效果更清晰。

总结

  1. 亮暗交界点检测的核心是二值化后计算相邻像素差值,需重点防护像素索引越界;
  2. 鼠标交互的关键是回调函数 + 全局变量,区分按下、拖拽、松开三类事件;
  3. 两个功能可结合使用,先自动检测边缘,再通过鼠标交互标注 / 修正结果,适配边缘定位、缺陷标注等场景。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐