博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenCV暗通道去雾算法在内窥镜视频流中的应用
阅读量:3905 次
发布时间:2019-05-23

本文共 4175 字,大约阅读时间需要 13 分钟。

OpenCV暗通道去雾算法在内窥镜视频流中的应用

本文算法基于大气去雾模型,以及何凯明博士的暗通道先验的理论思想,细化到内窥镜图像处理领域,做了一些速度上的提升以及优化。针对内窥镜视频必有反光,且手术腔内光强不会发生剧烈变化的特点,因此讲光强估计值A直接定义为255,减少了每帧图像在估算光强值时的时间。其他领域可能不适用该算法。

#include
#include
using namespace cv;using namespace std;//block模板大小与omega作用程度这两个参数可调整int block = 3;//每个像素点的周围block*block的矩形,block越大,速度越快,失真越明显double omega = 0.7;//除雾的程度,取值范围为[0,1],值越大,处理后图像颜色越深Mat ori, out;//原始Mat对象ori,处理后Mat对象out//定义三通道最小值函数min_3double min_3(double g, double b, double r){
double min; if (g <= b && g <= r)min = g; if (b <= g && b <= r)min = b; if (r <= g && r <= b)min = r; return min;}//定义矩阵内的最小值函数double mat_min(Mat matrix){
double min_in_matrix = 255.0; for (int i = 0; i < matrix.cols; i++) {
for (int j = 0; j < matrix.rows; j++) {
if (min_in_matrix > matrix.at
(i, j)) min_in_matrix = matrix.at
(i, j); } } return min_in_matrix;}//定义去雾函数如下Mat defogging(Mat image_in, int block, double omega){
//创建一个Mat类型的vector out_temp,其中维数是输入图像image_in的通道数 vector
out_temp(3); split(image_in, out_temp);//将原图ori的三通道分割并存储到out_temp内 //创建一个Mat类型的vector out_ROI vector
out_ROI(3); out_ROI[0] = Mat(block, block, CV_8UC1);//绿色8位单通道 out_ROI[1] = Mat(block, block, CV_8UC1);//蓝色8位单通道 out_ROI[2] = Mat(block, block, CV_8UC1);//红色8位单通道 //创建暗通道ROI对象,暗通道对象,输出图像的Mat对象。 Mat dark_ROI, dark_channel, out; dark_ROI = Mat(block, block, CV_8UC1);//暗通道ROI的8位单通道 dark_channel = Mat(image_in.rows, image_in.cols, CV_8UC1);//给暗通道分配大小 out = Mat(image_in.rows, image_in.cols, CV_8UC3);//去雾后的图像,三通道合并成out的Mat对象 //创建每次循环的处理区域work_ROI,并初始化坐标极其宽度高度 Rect work_ROI; work_ROI.x = 0;//矩形左上角横坐标 work_ROI.y = 0;//矩形左上角纵坐标 work_ROI.width = block;//矩形宽为block work_ROI.height = block;//矩形高为block //原图像ROI位置以及大小Rect类型储存 //按照论文方法的大气光强估计算法计算手术腔内光强估计值。 //在原始有雾图像中寻找对应的具有最高亮度的点的值,作为A值。 //并且由于是固定光源,腔内光强不会发生剧烈变化,因此无需每一帧的计算一次A。 //因为必定会有镜面反射点,于是直接令A_0,A_1,A_2都为255。 //简化排序每帧对于求A的一个大排序时间,优化在该领域算法复杂度。 //定义完毕手术腔内光强估计值 std::vector
A(3); A = { 255.0,255.0,255.0 };//公式中每个通道的光强估计值A //下面求暗通道dark_channel。 double min0 = 0, min1 = 0, min2 = 0, min = 0;//每个通道的最小值,以及整体最小值。 for (int i = 0; i < image_in.cols / block; i++)//外层循环循环原图列数/block 次 { for (int j = 0; j < image_in.rows / block; j++) //内层循环原图行数/block 次 { //分别计算三个通道内ROI的最小值 out_ROI[0] = out_temp[0](work_ROI);//在矩阵work_ROI内的绿色分量 min0 = mat_min(out_ROI[0]);//求出第一个像素点在out_ROI_0绿色分量的最小值 out_ROI[1] = out_temp[1](work_ROI);//蓝色分量在矩阵work_ROI内的小值 min1 = mat_min(out_ROI[1]);//求出第一个像素点蓝色分量的最小值 out_ROI[2] = out_temp[2](work_ROI);//红色分量在矩阵work_ROI内的小值 min2 = mat_min(out_ROI[2]);//求出第一个像素点红色分量的最小值 //求三个通道内最小值的最小值 即求min1 min2 min3中的最小值赋值给min min = min_3(min0, min1, min2);//min为这个ROI中暗原色 dark_ROI = dark_channel(work_ROI);//拷贝work_ROI给dark_channel后再赋给dark_ROI Mat temp = Mat(block, block, CV_8UC1, Scalar(min));//将最小值赋给temp temp.copyTo(dark_ROI);//按原色拷贝给dark_ROI //rect_ROI坐标转换到下一个矩形区块。 work_ROI.x = block * i;//工作区域向后移动block个像素 work_ROI.y = block * j;//工作区域向后移动block个像素 } } //下面求处理过后的图像 double tx;//透射率t(x) uchar ori_0, ori_1, ori_2;//输出图像每个通道像素值 for (int i = 0; i < image_in.rows; i++) { for (int j = 0; j < image_in.cols; j++) { tx = 1 - omega * dark_channel.at
(i, j)/255.0; //根据公式透射率=1-omega*min(dark_channel)/255,omega的值不要太大,否则颜色过暗视觉效果不好,得到每个点的透射率 if (tx < 0.1)tx = 0.1; //防止精度不够之后会出现除0的错误 //根据雾图模型 I(x)=J(x)t(x)+A(1-t(x))可以得到:J(x)=(I(x)-A)/t(x)+A 根据上式计算每个通道 ori_0 = (image_in.at
(i, j)[0] - A[0]) / tx + A[0]; //绿色通道每个像素点=(输入图像绿色通道值-光强估计值)/透射率+光强估计值 ori_1 = (image_in.at
(i, j)[1] - A[1]) / tx + A[1]; //蓝色通道每个像素点=(输入图像蓝色通道值-光强估计值)/透射率+光强估计值 ori_2 = (image_in.at
(i, j)[2] - A[2]) / tx + A[2]; //红色通道每个像素点=(输入图像红色通道值-光强估计值)/透射率+光强估计值 out.at
(i, j)[0] = ori_0; //输出图像绿色通道值写入 out.at
(i, j)[1] = ori_1; //输出图像蓝色通道值写入 out.at
(i, j)[2] = ori_2; //输出图像红色通道值写入 } } return out;}int main(){ cout << "请输入视频流路径: << endl; string PATH; cin >> PATH; VideoCapture capture; capture.open(PATH); while (true) { Mat ori; capture >> ori; imshow("原图像ori", ori); waitKey(20); //算法实现 out = defogging(ori, block, omega); imshow("处理后图像out", out); //算法结束 waitKey(20); } return 0;}

实现效果图如下:

处理前
处理后
可以看出效果差别。参数选取了block=3以及omega=0.7

总结:该算法思路,循环执行3*3的每一小块图片,将其在块中每个通道的最小值赋值给暗通道,在经过论文公式计算即可还输出去雾后图像,这也间接实现了对比度增强。

转载地址:http://xamen.baihongyu.com/

你可能感兴趣的文章
consistent hashing
查看>>
Inverted Index
查看>>
Crawler
查看>>
Bloom Filter
查看>>
Dynamic Programming
查看>>
Python Singleton
查看>>
Python hashmap
查看>>
python 切片
查看>>
interview sum
查看>>
HTTPs Control
查看>>
澳洲孕维生素
查看>>
Prenatal Vitamin Brands
查看>>
has_key or in
查看>>
Python sort list customisation
查看>>
Python sort dict by value
查看>>
Python collections deque - double-ended queue ()
查看>>
Python sort sorted OrderDict
查看>>
Python dict sort
查看>>
Python lambda
查看>>
Python modify string in place
查看>>