Opencv实现暗通道先验去雾算法
2017-10-03 10:58
253 查看
今天读了何凯明博士的《Single Image Haze Removal Using Dark Channel Prior》,用opencv实现了一遍。
其中,暗通道及T(x)采用腐蚀erode算法。
具体代码如下:
class hazeOutProcesser { public: hazeOutProcesser(const Mat& srcImg) { this->srcImg = srcImg.clone(); } hazeOutProcesser(){} void getDarkChannel(const Mat& src, Mat& dst) { Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); // erode(src, dst, element); morphologyEx(src, dst, MORPH_ERODE, element); // Mat temp = dst.clone(); // bilateralFilter(temp, dst, 25, 25*2, 25/2); cvtColor(dst, dst, COLOR_BGR2GRAY); } std::pair<Mat, Mat> getAtmosphere(const Mat& sortedIndex, const Mat& srcImg, double rate = 0.001) { long n_pixel = srcImg.rows * srcImg.cols; long n_search = n_pixel * rate; Mat srcImgVector = srcImg.reshape(1, n_pixel).clone(); //1channel, 3rows(b, g, r) //(n_pixel, 3) cout << srcImgVector.rows << ", " << srcImgVector.cols << endl; Mat accumulator = Mat::zeros(1, 3, CV_32FC1); //[(32f)0, (32f)0, (32f)0] for(int i = 0; i < n_search; ++i) { int index = sortedIndex.at<int>(i); Mat temp = srcImgVector.rowRange(index, index + 1).clone(); //row:index accumulator += temp; } Mat atmosphere = accumulator / n_search; for(int i = 0; i < n_pixel; ++i) { srcImgVector.rowRange(i, i + 1) = srcImgVector.rowRange(i, i + 1).mul(1 / atmosphere); } srcImgVector = srcImgVector.reshape(3).reshape(3, srcImg.rows); // imshow("srcImgVector", srcImgVector); // cout << srcImgVector.rows << ", " << srcImgVector.cols << endl; 4000 return std::make_pair(atmosphere, srcImgVector); } Mat getTransmission(const Mat& srcImg_divide_atmosphere) { float omega = 0.95; Mat darkchannel_SDA; getDarkChannel(srcImg_divide_atmosphere, darkchannel_SDA); darkchannel_SDA *= omega; darkchannel_SDA = 1 - darkchannel_SDA; // imshow("sda", darkchannel_SDA); return darkchannel_SDA; } Mat hazeOut(const Mat& srcImg, const Mat& T, const Mat& A) { const float T0 = 0.1; // long n_pixel = srcImg.rows * srcImg.cols; // Mat srcImgVector = srcImg.reshape(1, n_pixel); // for(int i = 0; i < n_pixel; ++i) { // srcImgVector.rowRange(i, i + 1) -= A; // } /*-------------------need improve------------------- I use a loop to calculate the result matrix but using maxtrix directly might speed up the procession */ Mat hazeout(srcImg.size(), CV_32FC3); for(size_t r = 0; r < hazeout.rows; ++r) { for(size_t c = 0; c < hazeout.cols; ++c) { hazeout.at<Vec3f>(r, c) = Vec3f((srcImg.at<Vec3f>(r, c)[0] - A.at<float_t>(0, 0)) / max(T.at<float>(r, c), T0) + A.at<float_t>(0, 0), (srcImg.at<Vec3f>(r, c)[1] - A.at<float_t>(0, 1)) / max(T.at<float>(r, c), T0) + A.at<float_t>(0, 1), (srcImg.at<Vec3f>(r, c)[2] - A.at<float_t>(0, 2)) / max(T.at<float>(r, c), T0) + A.at<float_t>(0, 2)); } } return hazeout; } void process() { getDarkChannel(srcImg, darkchannel); Mat matVector = darkchannel.reshape(1, 1); //(1, 116749) // cout << matVector.rows << ", " << matVector.cols << endl; Mat_<int> sortIndex; sortIdx(darkchannel, sortIndex, CV_SORT_EVERY_ROW | SORT_DESCENDING); std::pair<Mat, Mat> p = getAtmosphere(sortIndex, srcImg); /*-------check minimum------------- double min = 0; minMaxLoc(transmission, &min); cout << "min:" << min << endl; */ Mat transmission = getTransmission(p.second); hazeOut(srcImg, transmission, p.first).convertTo(dstImg, CV_8UC3, 255, 0); } void setInput(const Mat& input) { srcImg = input.clone(); } Mat getDarkChannelOutput() { return darkchannel; } Mat getOutput() { return dstImg; } private: Mat srcImg; Mat dstImg; Mat darkchannel; };
#include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char const *argv[]) { Mat srcImg = imread("../../../data/sea1.jpg"); assert(srcImg.data && srcImg.channels() == 3); srcImg.convertTo(srcImg, CV_32FC3, 1.0 / 255, 0); hazeOutProcesser processer; processer.setInput(srcImg); processer.process(); imshow("darkchannel1", processer.getDarkChannelOutput()); imshow("src1", srcImg); imshow("hazeout1", processer.getOutput()); srcImg = imread("../../../data/sea2.png"); assert(srcImg.data && srcImg.channels() == 3); srcImg.convertTo(srcImg, CV_32FC3, 1.0 / 255, 0); processer.setInput(srcImg); processer.process(); // imshow("darkchannel2", processer.getDarkChannelOutput()); imshow("src2", srcImg); imshow("hazeout2", processer.getOutput()); srcImg = imread("../../../data/sea4.jpg"); assert(srcImg.data && srcImg.channels() == 3); resize(srcImg, srcImg, Size(), 0.5, 0.5); srcImg.convertTo(srcImg, CV_32FC3, 1.0 / 255, 0); processer.setInput(srcImg); processer.process(); // imshow("darkchannel2", processer.getDarkChannelOutput()); imshow("src3", srcImg); imshow("hazeout3", processer.getOutput()); waitKey(); return 0; }
后记
为了提高运算速度,尽量使用矩阵运算,当然以上还有需要改善的地方。当然,本人水平有限,若有地方存在问题,还欢迎留言一起探讨!
相关文章推荐
- OpenCV实践之路——基于暗通道先验的去雾算法简单实现
- 图像去雾之何凯明暗通道先验去雾算法原理及c++代码实现
- 暗通道先验的去雾算法实现
- 图像去雾之何凯明暗通道先验去雾算法原理及c++代码实现
- 基于暗通道去雾算法的实现与优化(以)opencv在pc上的实现
- 图像去雾之何凯明暗通道先验去雾算法原理及c++代码实现
- 基于暗通道去雾算法的实现与优化(二)opencv在pc上的实现
- 匈牙利算法的C++实现(基于OpenCV)
- opencv实现视频实时去雾算法
- OpenCV图像增强算法实现(直方图均衡化、拉普拉斯、Log、Gamma)
- MeanShift和Camshift算法实现 Opencv
- OpenCV实现KNN算法
- 要点初见:OpenCV3中CUDA ORB特征提取算法的实现(GPU加速的ORB算法)
- 【算法+OpenCV】图像极坐标变换及基于OpenCV的实现
- 基于OpenCV的 SVM算法实现数字识别(四)---代码实现
- Camshift算法原理及其Opencv实现
- 7. 稀疏表示之OMP,SOMP算法及openCV实现
- 基于白点检测的数码相机自动白平衡算法实现(Opencv+vs)
- OpenCV2实现在图像中写入汉字,支持单通道、3通道图像
- PCA算法学习_1(OpenCV中PCA实现人脸降维)