Problem in plotting the matrix over an image.

I am required to read an image,find out its rgb channels and then in those channels separately,mark the pixels whose value exceeds above a certain threshold value.I wrote the following code for marking the pixels but they are not getting marked and I am getting the error that it exceeds matrix dimensions.What am I doing wrong in the code? Below is the code-
img=imread('test.jpg');
imshow(img)
redchannel=img(:,:,1);
greenchannel=img(:,:,2);
bluechannel=img(:,:,3);
rs=zeros(size(redchannel));
r1=cat(3,redchannel,rs,rs);
figure
imshow(r1)
gs=zeros(size(greenchannel));
g1=cat(3,gs,greenchannel,gs);
figure
imshow(g1)
bs=zeros(size(bluechannel));
b1=cat(3,bs,bs,bluechannel);
figure
imshow(b1)
[r,c,~]=size(img);
indx=zeros(r,c);
for i=1:r
for j=1:c
if ((redchannel(i,j))>=180)
indx(i,j)=1;
end
end
end
for i=1:r
for j=1:c
imshow(r1)
hold on
plot(indx(:,1),indx(:,2),'b*');
hold off
end
end

5 件のコメント

KSSV
KSSV 2016 年 11 月 16 日
Your code is taking hell lot of time: Use below modified code.
img=imread('Prachi Sharma image');
imshow(img)
%
redchannel=img(:,:,1);
greenchannel=img(:,:,2);
bluechannel=img(:,:,3);
%
rs=zeros(size(redchannel));
r1=cat(3,redchannel,rs,rs);
figure
imshow(r1)
%
gs=zeros(size(greenchannel));
g1=cat(3,gs,greenchannel,gs);
figure
imshow(g1)
%
bs=zeros(size(bluechannel));
b1=cat(3,bs,bs,bluechannel);
figure
imshow(b1)
%
[r,c,~]=size(img);
indx=zeros(r,c);
indx(redchannel>=180) = 1 ;
% for i=1:r
% for j=1:c
% if ((redchannel(i,j))>=180)
% indx(i,j)=1;
% end
% end
% end
for i=1:r
for j=1:c
imshow(r1)
hold on
plot(indx(:,1),indx(:,2),'b*');
drawnow
hold off
end
end
Can you tell me what you are trying to do here? Why loop needed here?
for i=1:r
for j=1:c
imshow(r1)
hold on
plot(indx(:,1),indx(:,2),'b*');
drawnow
hold off
end
end
Prachi Sharma
Prachi Sharma 2016 年 11 月 16 日
I am trying to check the matrix of every channel and when the value of any pixel in the channel exceeds a certain threshold value(in this case 180) it should get highlighted
Guillaume
Guillaume 2016 年 11 月 16 日
編集済み: Guillaume 2016 年 11 月 16 日
Important note:
redchannel = img(:,:,1);
rs = zeros(size(redchannel));
r1 = cat(3, redchannel, rs, rs);
That's very dangerous because there's no class specified in the zeros call. rs is always going to be of class double, whereas redchannel may be of a different class (if it comes from a jpeg image, it'll be uint8). You're then combining matrices of different classes which may not produce the result you expect.
Much safer would be:
redchannel = img(:,:,1);
rs = zeros(size(redchannel), class(redchannel)); %make sure rs is of the same class as redchannel
r1 = cat(3, redchannel, rs, rs);
or even better:
r1 = img; %r1 is same class as img
r1(:, :, [2 3]) = 0; %note that the double 0 gets converted to 0 of the class of r1
See this question and this question for how easy it is to be bitten by this.
Image Analyst
Image Analyst 2016 年 11 月 16 日
Do you want to change the actual pixel values, like make them red or something? OR do you want to leave the pixel values the same and just change how they are displayed, like use a colormap where those pixels are red, or use a binary overlay ?
Prachi Sharma
Prachi Sharma 2016 年 11 月 17 日
I need to take an image,find its 3 channels and then in every channel I need to check if any pixel is exceeding a certain threshold value.If a pixel exceeds a certain threshold value then those pixels should be marked or highlighted in the image of that channel.

サインインしてコメントする。

回答 (3 件)

KSSV
KSSV 2016 年 11 月 16 日

0 投票

clc; clear all ;
img=imread('Prachi Sharma image');
imshow(img)
%
redchannel=img(:,:,1);
greenchannel=img(:,:,2);
bluechannel=img(:,:,3);
%
rs=zeros(size(redchannel));
r1=cat(3,redchannel,rs,rs);
figure
imshow(r1)
%
gs=zeros(size(greenchannel));
g1=cat(3,gs,greenchannel,gs);
figure
imshow(g1)
%
bs=zeros(size(bluechannel));
b1=cat(3,bs,bs,bluechannel);
figure
imshow(b1)
%
[r,c,~]=size(img);
indx=NaN(r,c);
indx(redchannel>=180) = 1 ;
%
imshow(r1) ;
x = 1:c ;
y = 1:r ;
[X,Y] = meshgrid(x,y) ;
hold on
plot3(X,Y,indx,'*b') ;

3 件のコメント

Prachi Sharma
Prachi Sharma 2016 年 11 月 16 日
編集済み: Prachi Sharma 2016 年 11 月 16 日
Hey thank you it is working.I do have a question though,why have you taken first loop till columns and another loop till rows.Why can't it be the other way round?
KSSV
KSSV 2016 年 11 月 16 日
You try it out...this is the way the matrix size of x,y making equal to indx. Do consider the Guillaume comments.
Prachi Sharma
Prachi Sharma 2016 年 11 月 16 日
I tried it out,switching places of r and c and it didn't work that way.

サインインしてコメントする。

Guillaume
Guillaume 2016 年 11 月 16 日
編集済み: Guillaume 2016 年 11 月 16 日

0 投票

find will return the locations of all the values above the threshold, there's no need for a loop
img = imread('test.jpg');
redchannel = img(:, :, 1);
[row, column] = find(redchannel > 180); %no need for loop
redimage = img; redimage(:, :, [2 3]) = 0;
figure;
imshow(redimage);
hold on;
plot(column, row, 'b*'); %column, row <=> x, y. Stupid matlab can't decide on a single coordinate system!
and do the same for green and blue.
edit: also see my comment to the question about using zeros with no class specified.

11 件のコメント

Prachi Sharma
Prachi Sharma 2016 年 11 月 16 日
編集済み: Prachi Sharma 2016 年 11 月 16 日
Hey thanks it is working.I do have one more question,can you please explain this command "redimage(:,:,[2,3])=0",I could not understand [2,3] part in this. Also in the last command plot(column,row,'b*') why are you taking columns first and not rows.
P.S-The above question might sound stupid but I need to learn and not just copy.Thanks.
Guillaume
Guillaume 2016 年 11 月 16 日
redimage(:, :, [2 3]) selects all the rows, all the columns and only index 2 and 3 of the third dimension. index 2 is the green channel, and index 3 is the blue channel. In effect, this set all the green and blue value to 0. If you wanted to keep just the green channel, then:
img(:, :, [1 3]) = 0; %1and 3 is red and blue respectively
find use the normal matlab convention where the first value it returns is the row of the matrix, and the second value is the column of the matrix. plot and a few other functions (most of of the image processing toolbox, as well as gradient, meshgrid and maybe more) use a different coordinate system (x, y) where x corresponds to the columns, and y to the rows. This is matches the way you normally references coordinates outside matlab but as a result you end up with two different coordinates system where one is swapped compared to the other.
Personally, I think it's stupid (hence my comment in the code). In my opinion it would be much better to be internally consistent but that's what it is: plot uses (x, y) coordinates which is (column, row), find uses (row, column) which is (y, x).
Image Analyst
Image Analyst 2016 年 11 月 16 日
MATLAB is not the only one. Have you ever noticed the two conventions for numeric keypads - how your keyboard and phone are upside down with respect to each other? But yes, x,y and row,column trips up lots of people.
Prachi Sharma
Prachi Sharma 2016 年 11 月 17 日
@guillaume and @image analyst..Thanks a lot guys.
Prachi Sharma
Prachi Sharma 2016 年 11 月 17 日
@guillaume..Your code is not making the pixels who exceeds a certain threshold value zero in every channel.
Guillaume
Guillaume 2016 年 11 月 17 日
編集済み: Guillaume 2016 年 11 月 17 日
No, it doesn't and it can't. The code I've written does exactly and only this:
  • find the locations of pixels whose red pixels are above the threshold
  • creates a duplicate of the image where only the red channel is active
  • displays the image
  • overlays on the display blue stars at the locations found in the 1st step.
At no point does it alter the value of pixels above any threshold.
Prachi Sharma
Prachi Sharma 2016 年 11 月 17 日
Ok that works for me.I only have one concern left though.I need to "logical or" all the locations where the pixel values goes above the threshold in all the three channels. How do I do that?
KSSV
KSSV 2016 年 11 月 17 日
As suggested by Guillaume in other discussion.
[Y,X,V] = redchannel>=180 ;
Follow the same for other channels.
Prachi Sharma
Prachi Sharma 2016 年 11 月 17 日
I need to have different thresholds for every channel.
KSSV
KSSV 2016 年 11 月 17 日
Dear friend then type it..what is stopping you?
Prachi Sharma
Prachi Sharma 2016 年 11 月 17 日
編集済み: Prachi Sharma 2016 年 11 月 17 日
This will also work right?
%for redchannel
mask_r1=(redchannel<x);
newm1=uint8(mask_r1);
mult1=newm1.*redchannel;
%for greenchannel
mask_r2=(greenchannel<y);
newm2=uint8(mask_r2);
mult2=newm2.*greenchannel;
%for blue channel
mask_r3=(bluechannel<z);
newm3=uint8(mask_r3);
mult3=newm3.*bluechannel;
%or ing the result
ora=(newm1|newm1)|newm3;
uora=uint8(ora);
figure
imagesc(uora)
title('Ored result of all the threshold values');

サインインしてコメントする。

Image Analyst
Image Analyst 2016 年 11 月 17 日

0 投票

Try something like this:
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
% Make mask where ANY of the color channels is saturated.
saturatedPixels = redChannel == 255 | greenChannel == 255 | blueChannel == 255;
% Make red channel 255, and other color channels 0 where there is saturation
redChannel(saturatedPixels) = 255;
greenChannel(saturatedPixels) = 0;
blueChannel(saturatedPixels) = 0;
% Recombine separate color channels into a single, true color RGB image.
rgbImage = cat(3, redChannel, greenChannel, blueChannel);
imshow(rgbImage);
Now your RGB image will be pure red wherever ANY pixel of ANY color channel is saturated (value of 255). For an image in the range 0-1, use 1 instead of 255. For a uint16 image, use 65535 instead of 255.

カテゴリ

質問済み:

2016 年 11 月 16 日

回答済み:

2016 年 11 月 17 日

Community Treasure Hunt

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

Start Hunting!

Translated by