Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find haze of an image on MATLAB?

I want to compute the extent of haze of an image for each block. This is done by finding the dark channel value that is used to reflect the extent of haze. This concept is from Kaiming He's paper on a Single Image Haze Removal using Dark Channel Prior.

The dark channel value for each block is defined as follows:

where I^c (x',y') denotes the intensity at a pixel location (x',y') in color channel c (one of Red, Green, or Blue color channel), and omega(x,y) denotes the neighborhood of the pixel location (x',y').

I'm not sure how to translate this equation in MATLAB?

like image 742
ABC2013 Avatar asked Dec 26 '22 02:12

ABC2013


1 Answers

If I correctly understand what this equation is asking for, you are essentially extracting pixel blocks centered at each (x,y) in the image, you determine the minimum value within this pixel block for the red, green, and blue channels. This results in 3 values where each value is the minimum within the pixel block for each channel. From these 3 values, you choose the minimum of these and that is the final result for a location (x,y) in the image.

We can do this very easily with ordfilt2. What ordfilt2 does is that it applies an order-statistics filter to your image. You specify a mask of which pixels needs to be analyzed in your neighbourhood, it gathers those pixels in the neighbourhood that are deemed valid and sorts their intensities. You then you choose the rank of the pixel you want in the end. A lower rank means a smaller value while a larger rank denotes a larger value. In our case, the mask would be set to all logical true and is the size of the neighbourhood you want to analyze. Because you want a minimum, you would choose rank 1 of the result.

You would apply this to each red, green and blue channel, then for each spatial location, choose the minimum out of the three. Therefore, supposing your image was stored in im, and you wanted to apply a m x n neighbourhood to the image, do something like this:

%// Find minimum intensity for each location for each channel
out_red = ordfilt2(im(:,:,1), 1, true(m, n));
out_green = ordfilt2(im(:,:,2), 1, true(m, n));
out_blue = ordfilt2(im(:,:,3), 1, true(m, n));

%// Create a new colour image that has these all stacked
out = cat(3, out_red, out_green, out_blue);

%// Find dark channel image
out_dark = min(out, [], 3);

out_dark will contain the dark channel image you desire. The key to calculating what you want is in the last two lines of code. out contains the minimum values for each spatial location in the red, green and blue channels and they are all concatenated in the third dimension to produce a 3D matrix. After, I apply the min operation and look at the third dimension to finally choose which out of the red, green and blue channels for each pixel location will give the output value.

With an example, if I use onion.png which is part of MATLAB's system path, and specify a 5 x 5 neighbourhood (or m = 5, n = 5), this is what the original image looks like, as well as the dark channel result:

enter image description here

enter image description here


Sidenote

If you're an image processing purist, finding the minimum value for pixel neighbourhoods in a grayscale image is the same as finding the grayscale morphological erosion. You can consider each red, green or blue channel to be its own grayscale image. As such, we could simply replace ordfilt2 with imerode and use a rectangle structuring element to generate the pixel neighbourhood you want to use to apply to your image. You can do this through strel in MATLAB and specify the 'rectangle' flag.

As such, the equivalent code using morphology would be:

%// Find minimum intensity for each location for each channel
se = strel('rectangle', [m n]);
out_red = imerode(im(:,:,1), se);
out_green = imerode(im(:,:,2), se);
out_blue = imerode(im(:,:,3), se);

%// Create a new colour image that has these all stacked
out = cat(3, out_red, out_green, out_blue);

%// Find dark channel image
out_dark = min(out, [], 3);

You should get the same results as using ordfilt2. I haven't done any tests, but I highly suspect that using imerode is faster than using ordfilt2... at least on higher resolution images. MATLAB has highly optimized morphological routines and are specifically for images, whereas ordfilt2 is for more general 2D signals.

like image 150
rayryeng Avatar answered Jan 01 '23 01:01

rayryeng