#include "stdafx.h" #include "DecreaseHazeControl.h" #include "omp.h" // 多核编程 #include "histProject.h" //#include "DarkChannelDehaze.h" // 计算暗通道最大值:A_MAX double GetDarkChannelMaxVal(const cv::Mat &img) { try { // 输入有效性验证 if (img.empty() == true || img.type() != 16 || img.cols <= 0 || img.rows <= 0) { return 0; } const int patch = 8; // 图像尺寸 int imgWidth = img.cols; int imgHeight = img.rows; // 边界扩展图像 cv::Mat Mid(imgHeight + 2 * patch, imgWidth + 2 * patch, CV_8UC3); cv::copyMakeBorder(img, Mid, patch, patch, patch, patch, IPL_BORDER_REFLECT); // 暗通道图像 cv::Mat DarkChannel(imgHeight, imgWidth, CV_8UC1); for (int i = 0; i < imgHeight; ++i) { for (int j = 0; j < imgWidth; ++j) { // 局部区域 cv::Mat patchRegion = Mid(cv::Rect(j, i, 2 * patch, 2 * patch)); // 通道分离 std::vector planes; cv::split(patchRegion, planes); // 求取三个通道的最小值 double minB = 0, minG = 0, minR = 0; cv::minMaxLoc(planes[0], &minB); cv::minMaxLoc(planes[1], &minG); cv::minMaxLoc(planes[2], &minR); // 给暗通道复制 double minVal = min(min(minB, minG), minR); DarkChannel.at(i,j) = static_cast(minVal); // 内存释放 planes.clear(); } } // 计算暗通道最大值 double minDarkChannel = 0.0; double maxDarkChannel = 0.0; cv::minMaxLoc(DarkChannel, &minDarkChannel, &maxDarkChannel); // 释放暗通道图像 DarkChannel.release(); return maxDarkChannel; } catch(cv::Exception &e) { e.msg; return 0; } catch(...) { return 0; } } //求取三个通道中最小值,然后以最小值组成一幅灰度图 bool GetMinChannel(const cv::Mat &img, cv::Mat& dark) { try { // 输入有效性判断 if (img.empty() == true || img.type() != CV_8UC3) { return false; } std::vector planes; cv::split(img, planes); cv::min(planes[0], planes[1], dark); cv::min(planes[2], dark, dark); planes.clear(); return true; } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } } // 计算图像V bool GetImgV(const cv::Mat &MinChannel,const cv::Mat &Diff, const cv::Mat &Smooth, cv::Mat & DstV, double degree = 0.78) { try { // 输入有效性判断 // 1空值判断 if (MinChannel.empty() == true || Diff.empty() == true || Smooth.empty() == true) { return false; } // 2图像类型判断 if (MinChannel.type() != CV_8UC1 || Diff.type() != CV_8UC1 || Smooth.type() != CV_8UC1) { return false; } // 3图像尺寸判断 if (MinChannel.cols <= 0 || MinChannel.cols != Diff.cols || Diff.cols != Smooth.cols || MinChannel.rows <= 0 || MinChannel.rows != Diff.rows || Diff.rows != Smooth.rows) { return false; } if (degree < 0) { degree = 0; } else if (degree > 1) { degree = 1; } // 图像属性 int ImgWidth = MinChannel.cols; int ImgHeight = MinChannel.rows; // 创建:DstV DstV.create(cv::Size(ImgWidth, ImgHeight), CV_8UC1); // DstV 检查 if (DstV.empty() == true) { return false; } // 连续性判断以提高速度 if (DstV.isContinuous()) { ImgWidth *= ImgHeight; ImgHeight = 1; } // 计算DstV值 for(int i = 0; i < ImgHeight; ++i) { const uchar* pMinChannel = MinChannel.ptr(i); const uchar* pDiff = Diff.ptr(i); const uchar* pSmooth = Smooth.ptr(i); uchar* pDstV = DstV.ptr(i); for(int j = 0; j < ImgWidth; ++j) { double val = degree * max(uchar(min(uchar((*pMinChannel++) - (*pDiff++)), (*pSmooth++))), uchar(0)); (*pDstV++) = static_cast(val); } } return true; } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } } // 获取无雾图像 bool GetHazeFreeImg(const cv::Mat& img, const cv::Mat &ImgV, double A_MAX, cv::Mat &HazeFree) { try { // 输入有效性判断 if (img.empty() == true || img.type() != CV_8UC3 || img.cols <= 0 || img.rows <= 0 || ImgV.empty() == true || ImgV.type() != CV_8UC1 || ImgV.cols <= 0 || ImgV.rows <= 0 || A_MAX < 0 || A_MAX > 255 || img.cols != ImgV.cols || img.rows != ImgV.rows) { return false; } // 图像尺寸 int imgWidth = img.cols; int imgHeight = img.rows; // 创建输出图像 HazeFree.create(imgHeight, imgWidth, CV_8UC3); if (HazeFree.empty() == true) { return false; } #pragma omp parallel for for (int j = 0; j < imgWidth; ++j) { for (int i = 0; i < imgHeight; i++) { double V = ImgV.at(i, j); cv::Vec3b vec = img.at(i, j); for (int k = 0; k < 3; k++) { double VAB = 0; if (V != A_MAX) { VAB = fabs(vec[k] - V)/(fabs(1 - V/A_MAX)); } if (VAB > 255) { vec[k] = 255; } else { vec[k] = static_cast(VAB); } } HazeFree.at(i, j) = vec; } } return true; } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } } //功能:图像去雾控制 //输入: 1. img 输入图像 // 2. A_MAX 控制去雾效果, A_MAX < 0 时,自适应计算(特别耗时); 有效范围【0,255】,异常值自适应 // 3. degree 控制去雾效果, 有效范围【0,1】,异常值自适应 //输出: 1. HazeFree 输出图像 // 2. 返回值:处理成功返回true,失败返回false bool DeHazeImg(const cv::Mat &img, cv::Mat &HazeFree, double A_MAX, double degree) { try { // 单通道 红外图像细节增强 作者:王家星 if (img.type() == CV_8UC1) { if (A_MAX != 0) { // 高斯无约束 return GNRHP(HazeFree,img, false); } else { // 高斯约束 return GRHP(HazeFree, img, true); } } else { // 王家星算法 // 三通道 if (A_MAX < 0) { A_MAX = GetDarkChannelMaxVal(img); } if (A_MAX > 255) { A_MAX = 255; } cv::Mat Dark; cv::Mat Smooth; cv::Mat Diff; cv::Mat V; // 获取暗通道 if (GetMinChannel(img, Dark) == false) { return false; } // 高斯模糊 cv::GaussianBlur(Dark, Smooth, cv::Size(5, 5), 1.667); // 计算Diff cv::absdiff(Dark, Smooth, Diff); // 计算V if (GetImgV(Dark, Diff, Smooth, V, degree) == false) { return false; } // 计算HazeFree if (GetHazeFreeImg(img, V, A_MAX, HazeFree) == false) { return false; } return true; } } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } } // ImgStru结构下的图像去雾控制 //功能:图像去雾控制 //输入: 1. src 输入图像结构体 // 2. A_MAX 控制去雾效果, A_MAX < 0 时,自适应计算(特别耗时); 有效范围【0,255】,异常值自适应 // 3. degree 控制去雾效果, 有效范围【0,1】,异常值自适应 //输出: 1. dst 输出图像结构体 // 2. 返回值:处理成功返回true,失败返回false bool ImgStruDeHazeControl(ImgStru* src, ImgStru* dst, int A_MAX, double degree) { try { // src dst 有效性验证 if (src == NULL || dst == NULL || src->ImgWidth <=0 || src->ImgHeight <= 0 || src->buff == NULL) { return false; } // 属性复制 dst->ImgWidth = src->ImgWidth; dst->ImgHeight = src->ImgHeight; dst->bitcount = src->bitcount; dst->BoundingBox = src->BoundingBox; // 构建输入、输出图像 cv::Mat src_Img; // if (src->bitcount == 8) { src_Img = cv::Mat(src->ImgHeight, src->ImgWidth, CV_8UC1); } else if (src->bitcount == 24) { src_Img = cv::Mat(src->ImgHeight, src->ImgWidth, CV_8UC3); } else { return false; } // 步长:每行像素所占字节数 int lineByte = (src->ImgWidth * src->bitcount / 8); // 位图数据缓冲区的大小,即图像大小 unsigned int imgBufSize = static_cast(src->ImgHeight * lineByte); if (!src_Img.empty()) { // 图像数据复制 memcpy(src_Img.data, src->buff, imgBufSize); } else { return false; } // 构建输出图像 cv::Mat dst_Img; // 调用DeHazeImg算法,实现去雾控制 if (DeHazeImg(src_Img, dst_Img, A_MAX, degree) == true) { if (src == dst) { memcpy(dst->buff, dst_Img.data, imgBufSize); } else { SAFE_DELETE_ARRAY(dst->buff); dst->buff = new unsigned char[imgBufSize]; memcpy(dst->buff, dst_Img.data, imgBufSize); } } else { return false; } return true; } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } } //功能:图像去雾控制 //输入: 1. qbData 通用情报数据结构体 // 2. A_MAX 控制去雾效果, A_MAX < 0 时,自适应计算(特别耗时); 有效范围【0,255】 // 3. degree 控制去雾效果, 有效范围【0,1】 // 3. bSrcFirst 默认时,优先处理srcImg, srcImg-->dstImg // 否则,优先处理dstImg,dstImg——>dstImg //输出: 1. qbData 含图像去雾后图像的情报数据结构体 // 2. 返回值:处理成功返回true,失败返回false //说明: 首先判断图像数据有效性标识位,无效时直接返回,不做任何处理; bool QBStruDeHazeControl(QBStru *qbData, int A_MAX, double degree, bool bSrcFirst) { try { // 空值判断 if (qbData == NULL) { return false; } // 图像数据无效,直接返回false if (qbData->image.bValid == false) { return false; } // 优先处理srcImg if (bSrcFirst == true) { if (qbData->image.srcImg.buff != NULL && qbData->image.srcImg.ImgWidth > 0 && // srcImg 宽度验证 qbData->image.srcImg.ImgHeight > 0 ) // srcImg 高度验证 { return ImgStruDeHazeControl(&qbData->image.srcImg, &qbData->image.dstImg, A_MAX, degree); } else if (qbData->image.dstImg.buff != NULL && qbData->image.dstImg.ImgWidth > 0 && // dstImg 宽度验证 qbData->image.dstImg.ImgHeight > 0 ) // dstImg 高度验证 { // 输入dstImg,输出dstImg return ImgStruDeHazeControl(&qbData->image.dstImg, &qbData->image.dstImg, A_MAX, degree); } else // srcImg dstImg均无效 { return false; } } else { // 先看dstImg是否有效 if (qbData->image.dstImg.buff != NULL && qbData->image.dstImg.ImgWidth > 0 && // dstImg 宽度验证 qbData->image.dstImg.ImgHeight > 0 ) // dstImg 高度验证 { return ImgStruDeHazeControl(&qbData->image.dstImg, &qbData->image.dstImg, A_MAX, degree); }else if (qbData->image.srcImg.buff != NULL && qbData->image.srcImg.ImgWidth > 0 && // srcImg 宽度验证 qbData->image.srcImg.ImgHeight > 0 ) // srcImg 高度验证 { return ImgStruDeHazeControl(&qbData->image.srcImg, &qbData->image.dstImg, A_MAX, degree); } else // 情报结构体srcImg 和 dstImg 均无效 { return false; } } return true; } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } }