Search code examples
c#matlabhistogramaforgecdf

Converting CDF of histogram to c# from matlab?


How can I convert this matlab code to AForge.net+c# code?

cdf1 = cumsum(hist1) / numel(aa); 

I found that there is Histogram.cumulative method is present in Accord.net. But I dont know how to use.

Please teaching how to convert.

% Histogram Matching
%

clear
clc
close all

pkg load image

% 이미지 로딩
aa=imread('2.bmp');
ref=imread('ref2.png');

figure(1); imshow(aa); colormap(gray)
figure(2); imshow(ref); colormap(gray)

M = zeros(256,1,'uint8'); % Store mapping - Cast to uint8 to respect data type
hist1 = imhist(aa); % Compute histograms
hist2 = imhist(ref);

cdf1 = cumsum(hist1) / numel(aa); % Compute CDFs
cdf2 = cumsum(hist2) / numel(ref);

% Compute the mapping
for idx = 1 : 256
[~,ind] = min(abs(cdf1(idx) - cdf2));


M(idx) = ind-1;
end

% Now apply the mapping to get first image to make
% the image look like the distribution of the second image
out = M(double(aa)+1);

figure(3); imshow(out); colormap(gray)

Solution

  • Actually, I don't have a great knowledge of Accord.NET, but reading the documentation I think that ImageStatistics class is what you are looking for (reference here). The problem is that it cannot build a single histogram for the image and you have to do it by yourself. imhist in Matlab just merges the three channels and then counts the overall pixel occurrences so this is what you should do:

    Bitmap image = new Bitmap(@"C:\Path\To\Image.bmp");
    
    ImageStatistics statistics = new ImageStatistics(image);
    Double imagePixels = (Double)statistics.PixelsCount;
    
    Int32[] histR = statistics.Red.Values.ToArray();
    Int32[] histG = statistics.Green.Values.ToArray();
    Int32[] histB = statistics.Blue.Values.ToArray();
    Int32[] histImage = new Int32[256];
    
    for (Int32 i = 0; i < 256; ++i)
        histImage[i] = histR[i] + histG[i] + histB[i];
    
    Double cdf = new Double[256];
    cdf[0] = (Double)histImage[0];
    
    for (Int32 i = 1; i < 256; ++i)
        cdf[i] = (Double)(cdf[i] + cdf[i - 1]);
    
    for (Int32 i = 0; i < 256; ++i)
        cdf[i] = cdf[i] / imagePixels;
    

    In C#, an RGB value can be built from R, G and B channel values as follows:

    public static int ChannelsToRGB(Int32 red, Int32 green, Int32 blue)
    {
        return ((red << 0) | (green << 8) | (blue << 16));
    }