ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

水下照片又糊又偏色?用OpenCV三步就能救回来

水下照片又糊又偏色?用OpenCV三步就能救回来 水下照片又糊又偏色用OpenCV三步就能救回来【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv刚把AQUA相机拉出来的水下照片往检测流水线里一扔目标识别的召回率直接腰斩——画面整体发灰偏蓝绿目标边缘被一层雾糊住。这种片子人眼都费劲别指望算法能扛住。用 OpenCV 做水下图像颜色校正与去雾增强不用上复杂模型几条基础函数串起来就能把片子拉回可用状态。先把原理说清楚水就是一块磨砂玻璃光穿过水红光先被吸收得最狠所以你看到的照片只剩蓝绿悬浮的泥沙、藻类把光线往四面八方散画面像隔了一层毛玻璃——对比度被整体压下去。处理思路就是顺着光路反着来先把压扁的对比度撑开再把偏掉的色调掰正最后处理残留的脏点。第一步把被压扁的对比度撑开这一步解决的是整幅图灰蒙蒙、明暗都挤在中间的问题。全局的equalizeHist()对水下图基本不友好换成createCLAHE()的局部自适应均衡而且只作用在亮度通道上——这样局部最亮的区域不会被拉成过曝暗部细节又能被抬出来。Mat lab, bgr; cvtColor(img, lab, COLOR_BGR2LAB); // LAB 的 L 通道才是亮度 vectorMat ch; split(lab, ch); createCLAHE(2.0, Size(8, 8)).apply(ch[0], ch[0]); // 局部均衡clipLimit 2.0 封顶防过曝 merge(ch, lab); cvtColor(lab, bgr, COLOR_LAB2BGR);跑完应该看到背景的水雾和主体之间拉开明显反差主体轮廓清晰了。clipLimit 别一上来就拉满2.0~3.0 起步调太大会把气泡和噪点一起放大整幅图发颗粒感。撑开的对比度只是底子接下来把偏掉的色调掰正。第二步给蓝通道单独退烧这一步解决的是偏蓝绿的问题用pow()做伽马校正源码在modules/core/src/arithm.cpp。水下片子的偏色有个规律蓝通道整体偏亮、红通道整体偏暗。与其全局调不如挑偏得最狠的通道单独降曝光——伽马值小于 1 就是提亮大于 1 就是压暗。void gamma(Mat src, double g) { // 按通道套伽马曲线 Mat LUT(1, 256, CV_8U); for (int i 0; i 256; i) LUT.atuchar(i) saturate_castuchar(255 * pow(i / 255.0, g)); LUT.reshape(1, 3).convertTo(src, -1, 1, 0); // 每通道各查各的 LUT } vectordouble gain {1.0, 1.0, 1.4}; // BGR只压蓝通道 Mat t; convertScaleAbs(img, t, 1); // 拷贝 gamma(t, gain);对一张偏蓝的片子跑完蓝绿色罩明显退掉暖色细节回来整体不再发青。伽马参数按通道看直方图定哪个通道直方图整体右移偏亮就给哪个通道设大于 1 的值。第三步把残留脏点圈出来补掉这一步解决的是去雾后镜头脏点、气泡、划痕特别显眼的问题核心是inpaint()实现在modules/photo/src/inpaint.cpp。前面两步做完小的脏斑就成了画面里最扎眼的东西。用 Canny 找轮廓、筛面积把脏点标进 mask交给修复算法用周围像素填充。Mat blur, edges; GaussianBlur(t, blur, Size(5, 5), 1.2); // 先去噪Canny 才不会满屏碎边 Canny(blur, edges, 60, 140); vectorvectorPoint cs; findContours(edges, cs, RETR_LIST, CHAIN_APPROX_SIMPLE); Mat mask Mat::zeros(t.size(), CV_8U); for (auto c : cs) // 面积过滤只圈脏点大小的块 if (contourArea(c) 20) drawContours(mask, c, 0, Scalar(255), -1); inpaint(t, mask, t, 4, INPAINT_TELEA);跑完预期是 mask 圈住的脏斑被周围纹理自然填平肉眼看不到修补痕迹。把三步串成流水线原始水下照片 →GaussianBlurcreateCLAHE均衡亮度 → 对比度拉开的干净底子均衡后的图 → 分通道pow()伽马校正 → 偏蓝绿色调退掉、颜色接近真实校正后的图 → Canny 圈脏点 inpaint()修复 → 可交付检测/标注环节的最终图调参与避坑现象饱和度一加就出现纯红纯蓝的色块。→原因HSV 的 S 通道是 8 位直接 50会溢出截断。→解法加法前先saturate_cast或用convertScaleAbs限幅。现象全局equalizeHist一上整张图噪点炸开、局部过曝。→原因全局均衡把整幅图的分布强行拉平水下图的局部亮斑被放大。→解法改走 LAB 空间的 L 通道 CLAHE。现象去噪后气泡和细小纹理糊成一团。→原因高斯模糊是无差别平滑不区分边缘。→解法换bilateralFilter()它保边去噪边缘和噪声各论各的。现象inpaint半径一调大修复区像被涂了层腻子。→原因半径大意味着采样范围大周围纹理被平均化。→解法半径保持 2~5脏点大就先分割再逐个修。还能往哪儿走再深一点、水更浑的场景基础函数栈就到头了可以考虑 Retinex 类物理退散射模型OpenCV 里有createRetinex()的近似。目标尺度跨度大的检测任务把 CLAHE 的 tile 网格按目标尺寸缩放试试。批量数据想统一风格参考仓库里modules/photo/src/inpaint.cpp和modules/imgproc/src/histogram.cpp的写法自己封装一条流水线。现在挑一张自己的水下片子把这三段代码贴进项目跑一遍参数对着上面的坑位调半小时内你能拿到第一版可用的增强结果。【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表