基于c++的opencv亮度工具,可利用卡尺进行拖拽测量,仅提供全套源码加注释

直接上代码先看效果:按住鼠标左键拖动生成卡尺,松开自动计算区域亮度。支持多组测量,按'c'清屏,按'q'退出。核心代码分三块——卡尺绘制、事件处理、亮度计算,咱们拆开说。

先看卡尺绘制这骚操作:

// 画带刻度的卡尺线
void drawRuler(Mat& frame, Point start, Point end) {
    line(frame, start, end, Scalar(0, 255, 0), 2);  // 主轴线绿
    
    // 刻度生成算法
    double angle = atan2(end.y - start.y, end.x - start.x);
    for(int i=0; i<=10; i++){
        Point tick = start + (end - start) * i / 10;
        Point offset(10 * sin(angle), 10 * cos(angle));  // 垂直方向偏移
        line(frame, tick - offset, tick + offset, Scalar(0, 200, 0), 1);
    }
}

这个刻度生成用三角函数算垂直方向,比固定方向旋转更丝滑。注意这里offset计算用了sin/cos组合,实测比单用cos稳定,尤其处理对角线方向时不会抽搐。

鼠标事件处理是灵魂:

// 全局记录坐标和拖动状态
struct {
    Point start, current;
    bool dragging = false;
} rulerState;

// 鼠标回调
void onMouse(int event, int x, int y, int flags, void* userdata) {
    switch(event){
    case EVENT_LBUTTONDOWN:
        rulerState.start = Point(x, y);
        rulerState.dragging = true;
        break;
    case EVENT_MOUSEMOVE:
        if(rulerState.dragging){
            rulerState.current = Point(x, y);
            Mat temp = workingFrame.clone();
            drawRuler(temp, rulerState.start, rulerState.current);
            imshow("Brightness Tool", temp);
        }
        break;
    case EVENT_LBUTTONUP:
        rulerState.dragging = false;
        processROI(rulerState.start, Point(x, y));  // 触发亮度计算
        break;
    }
}

这里有个坑:直接在原图上绘制会导致残留线段。所以每次都要clone工作副本,这样松开鼠标时原图不受影响。processROI那步后面说。

基于c++的opencv亮度工具,可利用卡尺进行拖拽测量,仅提供全套源码加注释

亮度计算用了个取巧的方法:

void processROI(Point pt1, Point pt2) {
    Rect roi = Rect(pt1, pt2);  // 自动处理坐标正反
    if(roi.area() < 10) return;  // 防误触
    
    Mat region = srcImage(roi);
    Scalar mean = cv::mean(region);  // 三通道均值
    
    // 结果可视化
    rectangle(workingFrame, roi, Scalar(150, 75, 255), 2);
    string text = format("Lum:%.1f", mean[0]);
    putText(workingFrame, text, roi.br() + Point(5,15), 
            FONT_HERSHEY_SIMPLEX, 0.5, Scalar(200,100,255), 1);
}

这里mean取的是灰度值,如果原图是彩色的建议转成YUV空间取Y分量更准。不过实测RGB均值在多数情况够用,看需求改。

完整代码加了个亮度直方图的彩蛋——在窗口右下角用颜色条显示当前区域亮度分布,用cv::calcHist实现。编译注意链opencv_imgproc模块,有些发行版默认没带。

源码已扔Github(地址见文末),包含CMakeLists文件和测试图片。重点函数都写了中文注释,改参数建议优先调这几个:

  1. drawRuler里的刻度密度(10等分)
  2. processROI的亮度显示精度(.1f)
  3. 颜色阈值判断逻辑(默认没做)

这工具实测在工业检测场景挺实用,比如PCB板亮度均匀性检测。顺手改改还能做实时色差分析,有空再唠。

Logo

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

更多推荐