How we can maximize PSNR between RGB image and binary(0,1) image?

Hi, I have one RGB image and i want to create binary image from that with maximum PSNR. How i can do that?
In another word, The goal we are pursuing here is to make the output black and white image look like
Most images are the original color image from a PSNR perspective

 Réponse acceptée

Converting segmented RGB images into GRAYSCALE form is really good idea to process them.

14 commentaires

Do you have any code example for this?
How i can Converting segmented RGB images into GRAYSCALE?
% Extract the individual red, green, and blue color channels.
rgbImage=imread('trees.png');
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
% and then do a weighted average of them.
grayImage = 0.2989 * redChannel + 0.5870 * greenChannel + 0.1140 * blueChannel;
% These are standard weights. You can pick your own weights.
If this doesn't help, look for 'rgb2gray()' function.
Good luck!
mohammad nemat
mohammad nemat le 18 Nov 2021
Modifié(e) : mohammad nemat le 18 Nov 2021
Thanks, How did you select this weights for different channels and how can i compute those?
hello, I think it is scientific question. People use derivations on image processing. This is a document, just to show you. You do not need to read all:
https://web.archive.org/web/20160303201512/http://www.cis.rit.edu/mcsl/research/broadbent/CIE1931_RGB.pdf
This link didn't work for me and i couldn't download that pdf file.
Can you tell me about this in summarize?
how i can maximize psnr between binary and RGB image?
@mohammad nemat hi mohammad. these weights for grayscale images are taken related to RGB color's wavelengths.
------------------------------------------------------------------------------------------------------------------------------------------------
According to the other question that. These codes below solves your problem, I did them for you. Each time when you enter larger k value, the peaksnr will increase;
k=inputdlg('enter a k value to increase the peaksnr');
k=str2double(k);
ref = imread("strawberries.jpg");
ref = im2single(ref);
noisy = imnoise(ref,'salt & pepper',1./k);
[peaksnr,snr] = psnr(noisy,ref)
The reason the peaksnr increases according to k value because of the psnr function. Check the psnr function at that link: https://www.mathworks.com/matlabcentral/fileexchange/135-psnr
Hi, thanks a lot.
I had source image and binary image for compute PSNR and i don't have any noisy image to use that code.
img=imread('./test.png');
im2=imbinarize(img);
b = PSNR(img,im2);
like this code and i want to but i want to convert RGB image to binary image without any matlab function and do that from scratch and get maximum PSNR.
DGM
DGM le 20 Nov 2021
Modifié(e) : DGM le 20 Nov 2021
Those constants are the luma constants specified in ITR Rec 470 and 601. Though where they come from is unimportant, they are the same as used in rgb2gray().
rgbImage = imread('trees.png');
grayImage = rgb2gray(rgbImage);
That said, what is the meaningfulness of PSNR comparison between an RGB image and a binary image? I'm sure you could convert the color image to some form of grayscale and get a number out, but what would it mean conceptually? Are you trying to optimize some dithering algorithm?
I want to find the best solution for maximize psnr between RGB images and binary images.
I must find the best threshold for deciding from each pixel to use 0 or 255 for it and create a uint8 image with maximum PSNR.
Do you have any suggestions?
Again, if it's visual characteristics that are being optimized by some proxy metric, are you sure you're not trying to do dithering?
If you're trying to find an optimal threshold for segmentation, why would PSNR be relevant? IPT has graythresh() for calculating optimized global thresholds.
If you really want to find a global threshold with optimal PSNR (specifically) with an RGB input, then I suppose you can just do it.
A = im2double(imread('peppers.png'));
nf = 20; % number of tests
th = linspace(0,1,nf);
colors = {'r','g','b'};
hold on
for c = 1:size(A,3)
P = zeros(nf,1);
for f = 1:nf
P(f) = psnr(double(A(:,:,c)>th(f)),A(:,:,c));
end
[~,idx] = max(P);
bestthresh = th(idx) % threshold with best PSNR
plot(th,P,colors{c}) % show PSNR vs threshold
B(:,:,c) = A(:,:,c)>bestthresh;
end
bestthresh = 0.4737
bestthresh = 0.5263
bestthresh = 0.4737
figure
montage({A,double(B)})
Thnaks for your response. I said before my goal is to make the output black and white image look like
Most images are the original color image from a PSNR perspective. I must compute PSNR between RGB image and binary image in uint8 format.
A = im2double(imread('peppers.png'));
I want to get maximum PSNR(B,im2) in this photo it happend but in another photo not.
How i can do that and find best thershold for compute psnr?
nf = 20; % number of tests
th = linspace(0,1,nf);
B=uint8(A);
im2=imbinarize(B);
im2=uint8(im2);
b = psnr(B,im2);
colors = {'r','g','b'};
hold on
for c = 1:size(A,3)
P = zeros(nf,1);
for f = 1:nf
P(f) = psnr(double(A(:,:,c)>th(f)),A(:,:,c));
end
[~,idx] = max(P);
bestthresh = th(idx) % threshold with best PSNR
plot(th,P,colors{c}) % show PSNR vs threshold
B(:,:,c) = A(:,:,c)>bestthresh;
end
figure
montage({A,double(B)})
What is this part supposed to do?
% image is unit scale ([0 1])
A = im2double(imread('peppers.png'));
% casting as integer class quantizes the image
% now the image data is improperly-scaled and implicitly binarized at 50%
B=uint8(A);
% this doesn't do anything but change the class
% since the image has already been thresholded
im2=imbinarize(B);
% this converts the binary image back to an improperly-scaled uint8 image
im2=uint8(im2);
% the result is Inf because B is identical to im2
b = psnr(B,im2);
It doesn't do anything but generate two identical copies of the same 50% thresholded image and compare them to each other. The results aren't used for anything. Why was this added to the script?
You say you're trying to compare an RGB image to a "black and white" image. I don't know of canonical way to meaningfully compare the PSNR of two arrays of different size. If the added lines above were an example of intent, those don't generate a single-channel (i.e. black and white) binary output. They create a 3-channel (RGB) binary image, just like my example does.
The example I gave does channelwise comparison between an RGB image and an RGB binary image. If you insist on comparing incompatible arrays, you'll have to come up with a way. About the most sane way would be to collapse the RGB image to MxNx1 via rgb2gray(), but that wouldn't be a comparison between a binary image and RGB. That would be a comparison between a binary image and the luma of the original image. If you don't collapse the RGB image, how do you intend to consolidate a MxNx3 binary image into a single channel?
This might be how you would do the latter:
% do the same thing, but with luma only
A = im2double(imread('peppers.png'));
A = rgb2gray(A);
nf = 20; % number of tests
th = linspace(0,1,nf);
hold on
P = zeros(nf,1);
for f = 1:nf
P(f) = psnr(im2double(A>th(f)),A);
end
[~,idx] = max(P);
bestthresh = th(idx) % threshold with best PSNR
bestthresh = 0.5263
plot(th,P) % show PSNR vs threshold
figure
B = A>bestthresh;
montage({A,double(B)})
To summarize, you have three choices:
  • Compare RGB image to RGB mask: Demonstrated
  • Compare RGB image to BW mask: How is the mask generated? How are they compared?
  • Compare I image to BW mask: Demonstrated; Isn't a direct measure of similarity with RGB image
Pay attention to both class and data scaling. The representation of image data depends on an assumption of the nominal data range (i.e. what black is, what white is). This is implied by the numeric class. For integer classes, this is simply the full range supported by the bit width (e.g. [0 255] for uint8). All floating-point classes are assumed to be unit scale ([0 1]), just the same as logical images.
When you take a uint8 image and cast it with double(), you end up with a bunch of supramaximal data -- all the data is now whiter than white, since 255>>1. When you take a unit-scaled double image and cast it with uint8(), you destroy the image by rounding. When you take a logical image created by thresholding or with imbinarize() and then cast it using uint8(), no quantization damage occurs, but the data is still scaled 0 to 1. Since 1 is closer to 0 than it is to 255, the image is essentially black.
Unless you are paying attention to what's happening to the data, don't simply cast image data without rescaling accordingly. Tools like im2uint8() and im2double() check the input class and rescale the data accordingly. Use those.
I did everything in double, since the scaling of the result is consistent, regardless of input class. You can choose to do the whole thing in uint8, or you can just scale the result by 255.
clf
% same thing in uint8 instead of double
A = im2uint8(imread('peppers.png'));
nf = 20; % number of tests
th = linspace(0,255,nf);
colors = {'r','g','b'};
hold on
for c = 1:size(A,3)
P = zeros(nf,1);
for f = 1:nf
P(f) = psnr(im2uint8(A(:,:,c)>th(f)),A(:,:,c));
end
[~,idx] = max(P);
bestthresh = th(idx) % threshold with best PSNR
plot(th,P,colors{c}) % show PSNR vs threshold
B(:,:,c) = A(:,:,c)>bestthresh;
end
bestthresh = 120.7895
bestthresh = 134.2105
bestthresh = 120.7895
figure
montage({A,im2uint8(B)})
You can choose to adopt whatever class you want for your workflow, but be aware that there are a lot of operations which are not directly compatible with integer-class data, particularly operations with images of mixed class.
After a run of this code, I got PSNR=8.0089. I want to create function work like that imbinarize for making decisions and check each pixel one by one and replace 0 or 1 value for each one and get PSNR larger than 8.0089.
For example, I sent the previous code and I must use solution to do that.
For getting the maximum possible PSNR I must get the minimum MSE between RGB image and Binary image.
It's possible to suppose (0,1) or (0,255) in a generated image for each pixel
A = imread('peppers.png');
im2=imbinarize(A);
im2=uint8(im2);
b = psnr(A,im2);
You can certainly get a number, but again, what is the meaning of the comparison between these two images? The images are not remotely similar.
A = imread('peppers.png');
im2=imbinarize(A);
im2=uint8(im2);
b = psnr(A,im2) % it's a number
b = 8.0089
imshow(A); % the original RGB image
figure;
imshow(im2); % it's an approximately black RGB binary image
You mention trying to replicate imbinarize, but imbinarize doesn't do what you're describing. The closest might be the 'adaptive' method. If that's what you're after, just open up imbinarize() and read it. The private functions it calls should be in the toolbox directory.

Connectez-vous pour commenter.

Plus de réponses (3)

yanqi liu
yanqi liu le 18 Nov 2021
sir,may be use
if ndims(im) == 3
im = rgb2gray(im);
end
im = double(im2uint8(mat2gray(im)));
to get the same data type

3 commentaires

img=imread('./test.png');
im2=imbinarize(img);
b = PSNR(img,im2);
I can do that b this code but i want to convert RGB image to binary image without any matlab function and do that from scratch. do you have any suggestion?
sir,may be use direct threshol,such as
img=imread('./test.png');
im2=img(:,:,1)>50;
b = PSNR(img,im2);
thanks it was usefull.

Connectez-vous pour commenter.

I was not able to implement your codes into that probably psnr funtion only allows limited data types.

1 commentaire

It's worked for me. you should use psnr function from matlab with lowercase characters .

Connectez-vous pour commenter.

Image Analyst
Image Analyst le 20 Nov 2021
I agree with what Yusuf and DGM said, especially DGM who came up with a clever solution. He should post it as his own answer so we can vote for it and award him reputation points. They asked why you think you need it and that it may be irrelevant. Even when DGM specifically asked you why you need it you didn't really answer and just said basically "I need it because I need it" which is a non-answer. PSNR is usually used in comparing compression techniques, not comparing a 24 bit image to a 1-bit image. So what will you do with the thresholds DGM came up with?

2 commentaires

This is practice I must do. and I said my goal in the title and different situation.
What are you thinking about?
please let me know.
OK, I'll try to explain what I was thining about. When DGM and I asked you why you need a threshold to "maximize PSNR between RGB image and binary(0,1) image", your answer was that the reason why was in the title which is that you need to "maximize PSNR between RGB image and binary(0,1) image". So that's why I said you basically said "I need it because I need it."
Let's look at it a different way. Let's assume I asked you "I need a doohickey. Can you make me a doohickey?" And you replied "Why do you need a doohickey?" And I just replied "I already told you why -- I need a doohickey!"
Alright here is a common scenario.
  1. Person Q says "I need X".
  2. So person A makes X for Q and turns it over to Q.
  3. Then person Q says "That's no good - it doesn't work."
  4. A says why not?
  5. Q says "because it doesn't get me Y."
  6. A says "Well you didn't ask for Y initially. You only asked for X. But now since you tell me you want Y, I can tell you that getting X will not get you Y and is, in fact, the wrong approach that you asked for. If you really want Y, you need to do Z"
  7. A does Z and hands it over to Q, who is now happy with the solution.
That happens all too often and is why we need the full context of what you're trying to do.
In your situation you're asking how to do something that three people are telling you doesn't make sense and in meaningless and useless. You never said why so now I'm assuming it may be one of those quirky homework problems that essentially has no real world use. Often times, and I'm not saying that it applies to you, but people ask questions to try to get people to do their homework problems for them but they don't want to admit it because people will then just give them hints instead of full solutions. This is because some professors use plagiarism detectors to see if the student just copied code from an online forum, and we don't want them to get into trouble. That's why we often see code posted as an image instead of text - so the plagiarism detectors won't find it. Again, not saying that's you. Despite asking for the need, you have not said it's your homework so we'll assume it's not, but we just don't know why someone would ask for such a weird thing. Nevertheless, DGM tried to give you something you mght be happy with. We want to give you Y so you can get Z but you keep saying you need X.

Connectez-vous pour commenter.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by