Histogram equalization help in MATLAB - image

My code is shown below:
G= histeq(imread('F:\Thesis\images\image1.tif'));
figure,imshow(G);
The error message I got was the following and I'm not sure why it is appearing:
Error using histeq
Expected input number 1, I, to be two-dimensional.
Error in histeq (line 68)
validateattributes(a,{'uint8','uint16','double','int16','single'}, ...
Error in testFile1 (line 8)
G= histeq(imread('F:\Thesis\images\image1.tif'));

Your image is most likely colour. histeq only works on grayscale images. There are three options available to you depending on what you want to do. You can either convert the image to grayscale, you can histogram equalize each channel individually or what is perceptually better is to convert the image into the HSV colour space, histogram equalize the V or Value component, then convert back into RGB. I tend to prefer the last option for colour images. Therefore, one method will be an enhanced grayscale image, and the other two will be an enhanced colour image.
Option #1 - Convert to grayscale then equalize
G = imread('F:\Thesis\images\image1.tif');
G = histeq(rgb2gray(G));
figure; imshow(G);
Use rgb2gray to convert the image to grayscale, then equalize the image.
Option #2 - Equalize each channel individually
G = imread('F:\Thesis\images\image1.tif');
for i = 1 : size(G, 3)
G(:,:,i) = histeq(G(:,:,i));
end
figure; imshow(G);
Loop through each channel and equalize.
Option #3 - Convert to HSV, histogram equalize the V channel then convert back
G = imread('F:\Thesis\images\images1.tif');
Gh = rgb2hsv(G);
Gh(:,:,3) = histeq(Gh(:,:,3));
G = im2uint8(hsv2rgb(Gh));
figure; imshow(G);
Use the rgb2hsv function to convert a colour image into HSV. We then use histogram equalization on the V or Value channel, then convert back from HSV to RGB with hsv2rgb. Note that the output of hsv2rgb will be a double type image and so assuming that the original input image was uint8, use the im2uint8 function to convert from double back to uint8.

Related

Why is the whole picture turning red?

We’ve been trying to fix this program for hours, yet nothing seems to work, we just can’t figure out what the problem is. It is supposed to make the whole picture black white, besides the red pixels. (https://imgur.com/a/gxRm3N1 should look like that afterwards)
Here is the result after the using the program, the whole picture is turning red:
https://imgur.com/a/yWYVoIx
How can I fix this?
from image_helper import *
img = load_rgb_image("ara.jpg")
w, h = img.size
pixels = load_rgb_pixels("ara.jpg")
#img.show()
for i in range(w*h):
r,g,b = pixels[i]
new_r = 2*r
new_g = g // 2
new_b = b + 10
pixels[i] = (new_r, new_g, new_b)
new_img = new_rgb_image(w, h, pixels)
new_img.show()
There is an excellent solution implemented in MATLAB.
I was tempting to translate the code from MATLAB to Python (using OpenCV).
Convert the image to HSV color space.
Select "non-red" pixels. In HSV color space, the first channel is the hue - there is a range of hue for pixels that considered to be red.
Set the selected pixel saturation channel to 0. (Pixels with zero saturation are gray).
Convert the image back from HSV to BGR color space.
Here is the Python code (conversation of the original MATLAB code):
import cv2
# The following code is a Python conversion to the following MATLAB code:
# Original MATLAB code: https://stackoverflow.com/questions/4063965/how-can-i-convert-an-rgb-image-to-grayscale-but-keep-one-color
img = cv2.imread('roses.jpg') # Load image.
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Convert the image to HSV color space.
h = hsv[:, :, 0] # Note: in OpenCV hue range is [0,179]) The original MATLAB code is 360.*hsvImage(:, :, 1), when hue range is [0, 1].
s = hsv[:, :, 1] # Get the saturation plane.
non_red_idx = (h > 20//2) & (h < 340//2) # Select "non-red" pixels (divide the original MATLAB values by 2 due to the range differences).
s[non_red_idx] = 0 # Set the selected pixel saturations to 0.
hsv[:, :, 1] = s # Update the saturation plane.
new_img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) # Convert the image back to BGR space
# Show images for testing:
cv2.imshow('img', img)
cv2.imshow('new_img', new_img)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('new_img.jpg', new_img)
Result:
Notes:
For the method used for selecting the color range, refer to the original post.
The reference post has a simpler solution, using simple for loop (with inferior results), that more resembles your code.
Consider using this code as reference.

how to add rgb image and rgba image based on opacity value of the rgba image

lets say one image is shaped (x,y,3) and another (x,y,4). Now depending on whether the value of pixel in the 4th layer is 0 or non zero. I need to replace pixel values in the first image using the following rule.
if pixel in the 4th layer is 0 return image has values= value in (x,y,3) at that pixel in the rgb image
if non zero return image has value = value in value at that pixel in the rgba image
the return image should have shape (x,y,3)
If I understand you correctly, you effectively want to use the alpha part of the RGBA image as a binary mask. Assuming A is the rgb base image and B the rgba top image, both represented as numpy arrays:
mask = B[:, :, 3] > 0.5 # you can also use another threshold here
A[mask] = B[mask, 0:3]
Both images must have the same shape for this.
Alternatively, you can also overlay the second image on top of the first one using the alpha channel instead of using a binary mask:
A = (1-B[:,:,3])*A + B[:,:,3]*B[:,:,0:3]
You can do:
mask = img2[...,3] > 0
new_img = np.where(mask[...,None], img2[...,:3], img1)
Also without need for broadcasting:
mask = img2[...,3:] > 0
new_img = np.where(mask, img2[...,:3], img1)

MATLAB: Convert imagesc() RESULT to an image

Let say we have grayscale image im:
And use imagesc(im) to get:
With code:
im = rgb2gray(im2single(imread('tesla.jpg'))); % get image
h = imagesc(log(abs(fftshift(fft2(im))))); % imagesc handle
How can one convert the intensity graphic h (2nd image) to a standard RGB image (2x2 float matrix that one can manipulate, crop, etc) in matlab?
I don't need the axes, numbers or tics of the intensity image, I only need to maintain the color.
Thank you.
%turn off the axes
axis off
%save the image
saveas(h,'test.png')
%read the saved image
im_fft = imread('test.png');
%remove white border
sum_img = sum(im_fft,3); sum_img(sum_img(:) ~= 255*3) = 0; sum_img = logical(sum_img);
im_fft = im_fft(~all(sum_img,2), ~all(sum_img,1),:);
%Done!
figure, imshow(im_fft)
The resulting image can be used only for presentations/illustrations, not for analysis - quantization and sampling corrupts it significantly

Convert matlab.graphics.primitive.Image (output of imagesc) to rgb array

I'm using the MATLAB function
imagesc(my_gray_valued_image)
to visualize my_gray_valued_image: [1024x1024] double array with values from 0.0 - 1.0 (gray values) using colormaps like jet.
I want to store the output as a RGB image ([1024x1024x3] double array). However the output of the function is a Image object (matlab.graphics.primitive.Image) that contains the original array (Image.CData) but doesn't allow to extract the colorscaled image.
Following a similar (although confusingly cluttered) question (How to convert an indexed image to rgb image in MATLAB?) I tried the following, but that gave me a plain blue image:
RGB = ind2rgb(my_gray_valued_image, jet);
imshow(RGB);
here for arbitrary colormap:
im = rand(5); % input [0-1] image
figure;
h = imagesc(im); % imagesc handle
title('imagesc output')
cdata = h.CData; % get image data (if you don't have variable 'im')
cm = colormap(h.Parent); % get axes colormap
n = size(cm,1); % number of colors in colormap
c = linspace(h.Parent.CLim(1),h.Parent.CLim(2),n); % intensity range
ind = reshape(interp1(c,1:n,im(:),'nearest'),size(im)); % indexed image
rgb = ind2rgb(ind,cm); % rgb image
figure;
imshow(rgb,'InitialMagnification','fit');
title('rgb image')
You can use ind2rgb to convert an intensity image into RGB using a colormap of your choice; but make sure that the range of the input is from 1 to the number of colors in the colormap. This is because ind2rgb maps value 1 to the first color, 2 to the second etc.
im = rand(5,5); % example intensity image
cmap = jet(256); % desired colormap
result = ind2rgb(ceil(size(cmap,1)*im), cmap);
The reason why you are getting a blue image is that ind2rgb clips the values of the input image to the range from 1 to the number of colors in the colormap. So, if the input image has values between 0 and 1 they are all mapped to 1, that is, to the first color in the colormap.

Make a representative HSV image in matlab

I want to create an HSV image (or maybe a coordinate map) which shows that coordinates accurately.
I am using the following code and get an image like this the result of the following code which is not what I want.
img = rand(200,200);
[ind_x, ind_y] = ind2sub(size(img),find(isfinite(img)));
ind_x = reshape(ind_x,size(img));
ind_y = reshape(ind_y,size(img));
ind = ind_x.*ind_y;
figure, imagesc(ind); axis equal tight xy
Lets say you quantize the HSV space (0-1) into 256 bins. There will be 256*256*256 possible colors. We could fix a dimension (say saturation) and generate the matrix. Then there will be 256*256 colors.
[x1,x2]=meshgrid(linspace(0,1,256),linspace(0,1,256));
img(:,:,1)=x1;
img(:,:,2)=1; %fully saturated colors
img(:,:,3)=x2;
imgRGB=hsv2rgb(img); %for display purposes
imshow(imgRGB,[])
It will look different in RGB (that's where you would visualize). It looks similar to your image if you visualize HSV matrix (i.e. without converting it to RGB, but MATLAB doesn't know that its HSV)
imshow(img,[]);
The second image you have posted can be obtained with:
[x1,x2]=meshgrid(linspace(0,1,256),linspace(0,1,256));
img(:,:,1)=x1;
img(:,:,2)=0;
img(:,:,3)=x2;
imshow(img,[]) %visualizing HSV

Resources