1

I have the following code written in MATLAB, taken from this paper on page 3:

function [ ii_image ] = RGB2IlluminationInvariant( image, alpha )
ii_image = 0.5 + log(image(:,:,2)) - alpha*log(image(:,:,3)) - (1-alpha)*log(image(:,:,1));

This code should convert a 3-channel RGB image into its illumination invariant. I would like to know what the code is doing so that I can implement it in Java.

From what I can gather, it's calculating the logarithm of each red/green/blue pixel, and subtracting the values from each other, but the result isn't be an integer, so I can't apply it to Java's BufferedImage class when changing the RGB values. How can I emulate this function in Java?

Shan
  • 93
  • 1
  • 7
  • 1
    if image values are in range 0 to 1 then you can still save it in a BufferedImage as you can create a new color value using `new Color(0.1,0.2,0.3)`. If you want to use optimized library then take a look at JavaCV (opencv wrapper) here https://github.com/bytedeco/javacv – user8190410 May 29 '19 at 18:03

2 Answers2

1

It's not so difficult to convert the function to JAVA.
The following code sample is a MATLAB implementation that is kind of straight forward to convert to JAVA.

You should pay attention to the range and type of the input and output elements, and to the memory ordering.

Read the comments in the following code:

%function [ ii_image ] = RGB2IlluminationInvariant( image, alpha )

%Initialize input (for executing the example):
image = imread('peppers.png');
image = max(image, 1); %Replace zero values with 1, because log(0) is -Inf
image = double(image)/255; %Convert image to double in range [1/255, 1]. In JAVA, you should use double(pix)/255 if pix is a byte in range [0, 255].
alpha = 0.9;

ii_image = 0.5 + log(image(:,:,2)) - alpha*log(image(:,:,3)) - (1-alpha)*log(image(:,:,1));

%Assume elements in JAVA are stored in three 2D arrays (3 planes): R, G, B
%For example: double[][] R = new double[384][512];
%In Matlab 3 planes are:
R = image(:,:,1);
G = image(:,:,2);
B = image(:,:,3);
%II_image = 0.5 + log(G) - alpha*log(B) - (1-alpha)*log(R);
II_image = zeros(size(R));

%Equivalent for loop (simple to implement in JAVA):
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
image_width = size(image, 2);
image_height = size(image, 1);
for y = 1:image_height %Iterate rows, In JAVA: for(y = 0; y < image_height; y++)
    for x = 1:image_width %Iterate columns, In JAVA: for(x = 0; x < image_width; x++)
        r = R(y, x); %In JAVA: double r = R[y][x];
        g = G(y, x);
        b = B(y, x);

        p = 0.5 + log(g) - alpha*log(b) - (1.0-alpha)*log(r);

        II_image(y, x) = p;
    end
end

%Display ii_image
figure;imshow(ii_image, []);impixelinfo;title('ii\_image');

%Show difference (for debugging):
%figure;imshow(ii_image - II_image, []);impixelinfo

%Display minimum and maximum - values are not valid as pixel values in JAVA.
disp(['min(ii_image) = ', num2str(min(ii_image(:)))]);
disp(['max(ii_image) = ', num2str(max(ii_image(:)))]);


%Convert II_image range to [0, 1]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Find minimum and maximum (in JAVA you can do it inside the loop).
lo = min(II_image(:));
hi = max(II_image(:));

%Apply linear transformation:
II_image = (II_image - lo) / (hi - lo);

figure;imshow(II_image, []);impixelinfo;title('II\_image');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

I hope it helps you in the JAVA implementation.

Rotem
  • 30,366
  • 4
  • 32
  • 65
  • Thank you for the answer. I am close to completing it, but some of the calculations for `p` aren't in the range [0,1]. Some numbers are negative or more than 1. I get the R, G, B value of each pixel, and divide each R, G, B pixel by 255 after making sure it is nonzero. Then I do the log calculation but it isn't in the correct range. Do you know what might be the problem? – Shan May 30 '19 at 15:18
  • Do you have MATLAB installed? You can execute the MATLAB code, and see the result. – Rotem May 30 '19 at 15:23
  • I am getting: `min(ii_image) = -2.4237` and `max(ii_image) = 5.2882`. There is no guaranty that the computation results will be in range. – Rotem May 30 '19 at 15:27
  • Yes, the code works in MATLAB, and the ranges for my test images are the same. When I do this in Java, I can't use the result to set the RGB value, because it is not between [0,1]. Is there a way to convert those numbers to be in the range of [0,1]? – Shan May 30 '19 at 15:32
  • I added an example: find minimum and maximum, and from each element: subtract minimum and divide by (maximum - minimum). – Rotem May 30 '19 at 15:41
  • Implement it in a new loop (when you know the minimum and maximum). – Rotem May 30 '19 at 15:44
0

You can find a lot of matrix library in Java according to here. I suggest you can choose EJML to convert your logic into Java.

Qingfei Yuan
  • 1,196
  • 1
  • 8
  • 12