From f07885c1eb4c98dc52704517623b2e7df1ed616d Mon Sep 17 00:00:00 2001 From: JinweiClarkChao Date: Tue, 25 Aug 2015 12:27:20 +0800 Subject: initial complete --- DCP/DCP.vcxproj | 1 + DCP/DCP.vcxproj.filters | 3 ++ DCP/airlight.cpp | 134 +++++++++++++++++++++--------------------------- DCP/darkchannel.cpp | 34 ++++++------ DCP/dcp.cpp | 15 +++++- DCP/dcp_core.h | 5 ++ DCP/guidedfilter.cpp | 3 -- DCP/recover.cpp | 28 ++++++---- DCP/test.cpp | 14 +++++ DCP/transmission.cpp | 57 ++++++++++---------- README.md | 2 + 11 files changed, 159 insertions(+), 137 deletions(-) create mode 100644 DCP/test.cpp diff --git a/DCP/DCP.vcxproj b/DCP/DCP.vcxproj index eba571d..8d88b2c 100644 --- a/DCP/DCP.vcxproj +++ b/DCP/DCP.vcxproj @@ -88,6 +88,7 @@ + diff --git a/DCP/DCP.vcxproj.filters b/DCP/DCP.vcxproj.filters index b301b89..0992c1b 100644 --- a/DCP/DCP.vcxproj.filters +++ b/DCP/DCP.vcxproj.filters @@ -33,6 +33,9 @@ Source Files + + Source Files + diff --git a/DCP/airlight.cpp b/DCP/airlight.cpp index c6df18f..08f18d0 100644 --- a/DCP/airlight.cpp +++ b/DCP/airlight.cpp @@ -1,97 +1,79 @@ #include "dcp_core.h" +#include +#include +#include +#include -void Estimate_A(IplImage *DarkChannel, IplImage *InputImage, struct Max_Pixel_Selector *MaxPixel, double A[]) +using namespace std; + +struct Pixel { - double num = height * width * 0.001; - double num1per = num * 0.01; //num1per is the number of 1 percent of top 0.1 pixels - //k is the index of the color channel - int k = 0; - int patchsize; - int dark_i, dark_j; - uchar Max = 0; + int value; + int i, j; +}; - IplImage *mask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); - cvZero(mask); +void CalcAirlight(IplImage *darkchannel, IplImage *input, double A[]) +{ + int height = input->height; + int width = input->width; + int widthstep = input->widthStep; + int gwidthstep = darkchannel->widthStep; + int nch = input->nChannels; - int e = 0, i, j; - for (i = 1; i <= height; i++) + struct Pixel *v_darkchannel = (struct Pixel *)malloc(sizeof(struct Pixel) * height * width); + int count = 0; + for (int i = 0; i < height; i++) { - for (j = 1; j <= width; j++) + for (int j = 0; j < width; j++) { - MaxPixel[e].Pixel = *(uchar *)(DarkChannel->imageData + (i - 1) * gwidthstep + (j - 1)); - MaxPixel[e].i = i; - MaxPixel[e].j = j; - e++; + int value = *(uchar *)(darkchannel->imageData + i * gwidthstep + j); + struct Pixel p = { value, i, j }; + v_darkchannel[count++] = p; } } - sort(MaxPixel, MaxPixel + e, comp1); + sort(v_darkchannel, v_darkchannel + count, [](struct Pixel &a, struct Pixel &b){ return a.value > b.value; }); + + + IplImage *mask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); + cvZero(mask); - for (i = 0; i < num; i++) + for (int i = 0; i < count * 0.001; i++) { - dark_i = MaxPixel[i].i; - dark_j = MaxPixel[i].j; - *(uchar *)(mask->imageData + (dark_i - 1) * gwidthstep + (dark_j - 1)) = 255; - //只有当mask标记为255之后,才说明该块区域亮度值是在暗通道的前0.1%之内的 + struct Pixel p = v_darkchannel[i]; + *(uchar *)(mask->imageData + p.i * gwidthstep + p.j) = 255; } + - if (num1per < 9) - patchsize = 3; - else - patchsize = sqrt(num1per); - - for (k = 0; k < 3; k++) + for (int k = 0; k < 3; k++) { - int e, x, y; - int tmp = (patchsize - 1) / 2; - int st_row, ed_row; - int st_col, ed_col; + struct Pixel *v_channel = (struct Pixel *)malloc(sizeof(struct Pixel) * height * width); + int count = 0; - double A_tmp = 0; - double aver = 0; // aver 为指定大小patch内InputImage值的平均值 - int flag; //flag用来获取mask的标记 - - for (i = 1; i <= num; i++) + for (int i = 0; i < height; i++) { - aver = 0; - dark_i = MaxPixel[i].i; - dark_j = MaxPixel[i].j; - - st_row = dark_i - tmp, ed_row = dark_i + tmp; - st_col = dark_j - tmp, ed_col = dark_j + tmp; - - if (st_row <= 0) - st_row = 1; - if (ed_row>height) - ed_row = height; - if (st_col <= 0) - st_col = 1; - if (ed_col>width) - ed_col = width; - - e = 0; - for (x = st_row; x <= ed_row; x++) + for (int j = 0; j < width; j++) { - for (y = st_col; y <= ed_col; y++) - { - flag = *(uchar *)(mask->imageData + (x - 1) * gwidthstep + (y - 1)); - if (flag == 0) //未被标记说明该点不在前0.1%对应的区域内,跳过 - { - continue; - } - else - { - aver += *(uchar *)(InputImage->imageData + (x - 1) * widthstep + (y - 1) *nch + k); - e++; - } - } - } - aver /= e; - if (A_tmp < aver) - { - A_tmp = aver; + int flag = *(uchar *)(mask->imageData + i * gwidthstep + j); + if (flag == 0) + continue; + + int value = *(uchar *)(input->imageData + i * widthstep + j * nch + k); + struct Pixel p = { value, i, j }; + v_channel[count++] = p; } } - A[k] = A_tmp / 255.0; + + sort(v_channel, v_channel + count, [](struct Pixel &a, struct Pixel &b){ return a.value > b.value; }); + + int channel_airlight = 0; + for (int i = 0; i < count * 0.01; i++) + { + channel_airlight += v_channel[i].value; + } + channel_airlight /= (count * 0.01); + A[k] = channel_airlight; + + free(v_channel); } - cvReleaseImage(&mask); + free(v_darkchannel); } \ No newline at end of file diff --git a/DCP/darkchannel.cpp b/DCP/darkchannel.cpp index a6cd530..ab5a365 100644 --- a/DCP/darkchannel.cpp +++ b/DCP/darkchannel.cpp @@ -18,34 +18,38 @@ void CalcDarkChannel(IplImage *darkchannel, IplImage *input, int radius) int st_row, ed_row; int st_col, ed_col; - for (int i = 1; i <= height; i++) + for (int i = 0; i < height; i++) { - for (int j = 1; j <= width; j++) + for (int j = 0; j < width; j++) { st_row = i - radius, ed_row = i + radius; st_col = j - radius, ed_col = j + radius; - if (st_row <= 0) - st_row = 1; - if (ed_row > height) - ed_row = height; - if (st_col <= 0) - st_col = 1; - if (ed_col > width) - ed_col = width; + if (st_row < 0) + st_row = 0; + if (ed_row >= height) + ed_row = height - 1; + if (st_col < 0) + st_col = 0; + if (ed_col >= width) + ed_col = width - 1; + + int cur = 0; + int min = 300; - int min = 0; - int tmp[3]; for (int m = st_row; m <= ed_row; m++) { for (int n = st_col; n <= ed_col; n++) { for (int k = 0; k < 3; k++) - tmp[k] = *(uchar *)(input->imageData + (i - 1) * widthstep + (j - 1) * nch + k); - min = minbgr(tmp[0], tmp[1], tmp[2]); + { + cur = *(uchar *)(input->imageData + m * widthstep + n * nch + k); + if (cur < min) + min = cur; + } } } - *(uchar *)(darkchannel->imageData + (i - 1) * gwidthstep + (j - 1)) = min; + *(uchar *)(darkchannel->imageData + i * gwidthstep + j) = min; } } } diff --git a/DCP/dcp.cpp b/DCP/dcp.cpp index df4aad9..4e100c6 100644 --- a/DCP/dcp.cpp +++ b/DCP/dcp.cpp @@ -1,5 +1,8 @@ #include "dcp.h" +#include +using namespace std; + void dehaze(IplImage *recover, IplImage *input) { int height = input->height; @@ -11,8 +14,16 @@ void dehaze(IplImage *recover, IplImage *input) int darkchannelradius = MIN(width, height) * 0.02; - CalcDarkChannel(darkchannel, input, darkchannelradius); - + + double Airlight[3] = { 0.0, 0.0, 0.0 }; + CalcDarkChannel(darkchannel, input, darkchannelradius); + + CalcAirlight(darkchannel, input, Airlight); + + CalcTransmission(transmission, input, Airlight, darkchannelradius); + GuidedFilterColor(refine_transmission, input, transmission, 1e-6, 60); + CalcRecover(recover, input, refine_transmission, Airlight); + } diff --git a/DCP/dcp_core.h b/DCP/dcp_core.h index 3fb8c7c..85e4d59 100644 --- a/DCP/dcp_core.h +++ b/DCP/dcp_core.h @@ -5,5 +5,10 @@ #include void CalcDarkChannel(IplImage *darkchannel, IplImage *input, int radius); +void CalcAirlight(IplImage *darkchannel, IplImage *input, double A[]); +void CalcTransmission(IplImage *transmission, IplImage *input, double A[], int radius); +void CalcRecover(IplImage *result, IplImage *input, IplImage *transmission, double A[]); +void GuidedFilterColor(IplImage *q, IplImage *II, IplImage *p, double eps, int r); + #endif \ No newline at end of file diff --git a/DCP/guidedfilter.cpp b/DCP/guidedfilter.cpp index 46040ad..bfdf956 100644 --- a/DCP/guidedfilter.cpp +++ b/DCP/guidedfilter.cpp @@ -42,9 +42,6 @@ void GuidedFilterColor(IplImage *q, IplImage *II, IplImage *p, double eps, int r for (i = 1; i <= height; i++) { - if (i % 10 == 0) - printf("%d\n", i); - for (j = 1; j <= width; j++) { st_row = i - r, ed_row = i + r; diff --git a/DCP/recover.cpp b/DCP/recover.cpp index a99b0f2..5dbd75e 100644 --- a/DCP/recover.cpp +++ b/DCP/recover.cpp @@ -1,7 +1,13 @@ #include "dcp_core.h" -void Recover(IplImage *Result, IplImage *InputImage, double A[]) +void CalcRecover(IplImage *result, IplImage *input, IplImage *transmission, double A[]) { + int height = input->height; + int width = input->width; + int widthstep = input->widthStep; + int gwidthstep = transmission->widthStep; + int nch = input->nChannels; + double t0 = 0.1; double t, tmp_res; @@ -9,27 +15,29 @@ void Recover(IplImage *Result, IplImage *InputImage, double A[]) int e = 0, number = 0; double a = 0; - for (i = 1; i <= height; i++) + A[0] /= 255.0; + A[1] /= 255.0; + A[2] /= 255.0; + + for (i = 0; i < height; i++) { - for (j = 1; j <= width; j++) + for (j = 0; j < width; j++) { - t = real_trans[e++]; + t = *(uchar *)(transmission->imageData + i * gwidthstep + j); t /= 255.0; for (k = 0; k < 3; k++) { - a = *(uchar *)(InputImage->imageData + (i - 1) * widthstep + (j - 1) * nch + k); - a /= 255; - - tmp_res = ((a - A[k]) / MaxTwo(t, t0)) + A[k]; + a = *(uchar *)(input->imageData + (i) * widthstep + (j) * nch + k); + a /= 255.0; - real_recover[number++] = tmp_res; + tmp_res = ((a - A[k]) / MAX(t, t0)) + A[k]; if (tmp_res > 1) tmp_res = 1; else if (tmp_res < 0) tmp_res = 0; - *(uchar *)(Result->imageData + (i - 1) * widthstep + (j - 1) * nch + k) = tmp_res * 255.0; + *(uchar *)(result->imageData + (i) * widthstep + (j) * nch + k) = tmp_res * 255.0; } } } diff --git a/DCP/test.cpp b/DCP/test.cpp new file mode 100644 index 0000000..7efeeb7 --- /dev/null +++ b/DCP/test.cpp @@ -0,0 +1,14 @@ +#include "dcp.h" + +int main() +{ + IplImage *input = cvLoadImage("input.png"); + IplImage *result = cvCreateImage(cvGetSize(input), IPL_DEPTH_8U, 3); + dehaze(result, input); + + cvNamedWindow("Result"); + cvShowImage("Result", result); + cvWaitKey(); + + return 0; +} \ No newline at end of file diff --git a/DCP/transmission.cpp b/DCP/transmission.cpp index 5bb2ece..48a8299 100644 --- a/DCP/transmission.cpp +++ b/DCP/transmission.cpp @@ -1,51 +1,46 @@ #include "dcp_core.h" -void Estimate_transmission(IplImage *Transmission_maps, IplImage *InputImage, double A[], double heap[], double real_trans[]) +void CalcTransmission(IplImage *transmission, IplImage *input, double A[], int radius) { - double w = 0.95; - double tmp; - double tran; - int i, j, k; - int e = 0; + int width = input->width; + int height = input->height; + int widthstep = input->widthStep; + int gwidthstep = transmission->widthStep; + int nch = input->nChannels; - IplImage *tmp_Trans = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); + double w = 0.95; + + IplImage *normalized_input = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); - for (k = 0; k < 3; k++) + for (int k = 0; k < 3; k++) { - for (i = 1; i <= height; i++) + for (int i = 0; i < height; i++) { - for (j = 1; j <= width; j++) + for (int j = 0; j < width; j++) { - tmp = *(uchar *)(InputImage->imageData + (i - 1) * widthstep + (j - 1) * nch + k); - tmp /= A[k]; + double tmp = *(uchar *)(input->imageData + i * widthstep + j * nch + k); + tmp = tmp / A[k] * 255.0; - if (tmp > 255) - tmp = 255; - *(uchar *)(tmp_Trans->imageData + (i - 1) * widthstep + (j - 1) * nch + k) = tmp; + tmp = tmp > 255 ? 255 : tmp; + *(uchar *)(normalized_input->imageData + i * widthstep + j * nch + k) = tmp; } } } - Cal_DarkChannel(Transmission_maps, tmp_Trans, nInteger, heap); + CalcDarkChannel(transmission, normalized_input, radius); - for (i = 1; i <= height; i++) - { - for (j = 1; j <= width; j++) + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) { - tran = *(uchar *)(Transmission_maps->imageData + (i - 1) * gwidthstep + (j - 1)); - - tran /= 255.0; - tran = 1 - w * tran; + double tran = *(uchar *)(transmission->imageData + i * gwidthstep + j); - real_trans[e++] = tran * 255.0; + tran = 1 - w * (tran / 255.0); - if (tran > 1) - tran = 1; - else if (tran < 0) - tran = 0; + tran = tran > 1 ? 1 : tran; + tran = tran < 0 ? 0 : tran; - *(uchar *)(Transmission_maps->imageData + (i - 1) * gwidthstep + (j - 1)) = tran * 255; + *(uchar *)(transmission->imageData + i * gwidthstep + j) = tran * 255; } } - //cvSaveImage("Estimated-Trans.bmp", Transmission_maps); - cvReleaseImage(&tmp_Trans); + cvReleaseImage(&normalized_input); } diff --git a/README.md b/README.md index 4f6f576..5f1946b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ Implementation of Dark Channel Prior +This repo is still under development. + He K, Sun J, Tang X. Single image haze removal using dark channel prior[J]. Pattern Analysis and Machine Intelligence, IEEE Transactions on, 2011, 33(12): 2341-2353. -- cgit v1.2.3