Opencv 学习笔记:像素亮暗交界点检测 + 鼠标交互操作
·
在图像分析中,检测像素亮暗交界点(黑白边缘)、实现鼠标交互标注是基础实用技能。本文整合 “像素亮暗交界点定位” 和 “鼠标交互绘图” 两大功能,新手可快速掌握核心逻辑并直接复用。
核心代码实现
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_next | 255 = 白→黑交界,-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),视觉效果更清晰。
总结
- 亮暗交界点检测的核心是二值化后计算相邻像素差值,需重点防护像素索引越界;
- 鼠标交互的关键是回调函数 + 全局变量,区分按下、拖拽、松开三类事件;
- 两个功能可结合使用,先自动检测边缘,再通过鼠标交互标注 / 修正结果,适配边缘定位、缺陷标注等场景。
更多推荐
所有评论(0)