get pixel coordination by rgb values matlab - matlab

how can I get the x,y coordinates for pixels in an image by rgb values in matlab ?
for example : I've got an image that I want to locate the pixels coordinates od the black area in it..

If you want to find all coordinates of pixles with values (R, G, B) then
[y, x] = find(img(:,:,1)==R & img(:,:,2)==G & img(:,:,3)==B);
For black pixels choose R=0, G=0, B=0

There is a built-in function that does this: impixel.
From the official documentation:
Return Individual Pixel Values from Image
% read a truecolor image into the workspace
RGB = imread('myimg.png');
% determine the column c and row r indices of the pixels to extract
c = [1 12 146 410];
r = [1 104 156 129];
% return the data at the selected pixel locations
pixels = impixel(RGB,c,r)
% result
pixels =
62 29 64
62 34 63
166 54 60
59 28 47
Link: https://it.mathworks.com/help/images/ref/impixel.html
[EDIT]
Ok, I misunderstood your question. So to accomplish what you are looking for just use the following code:
img = imread('myimg.png');
r = img(:,:,1) == uint8(0);
g = img(:,:,2) == uint8(0);
b = img(:,:,3) == uint8(255);
[rows_idx,cols_idx] = find(r & g & b);
The example above finds all the pure blue pixels inside the image (#0000FF) and returns their indices. You can also avoid casting values to uint8, it should work anyway by implicitly converting values during comparison.

Related

Grouping neighbours in separate arrays in MATLAB

I have an annotated 512x512x3 fingerprint image, with the annotations being the positions of loops and deltas in the image. Red denotes loop, and blue denotes delta.
I need to find the position of these points. I can do this using impixel(), but I wanted a more automated approach.
I did the following:
x=[];
y=[];
for i = 1:512
for j = 1:512
marked = im(i,j,:);
if marked(:,:,1)==255
x=[x i];
y=[y j];
end
end
end
x = unique(x);
y = unique(y);
and got the positions of the pixels where the color red is the position of the loops.
My array y holds the y coordinates of all the red pixels, like this:
[116 117 118 119 120 121 122 191 192 193 194 195 196 197]
At first glance, it is clear that the values can be grouped into 2 groups, for the two red points. But I am unsure how to divide the values into two groups. I thought about creating a threshold using the mean of the values, but that might not work if the points are close by.
Any help might be useful.
If you know in advance how many red points there will be (2 in the example), you could use kmeans -
y_groups = kmeans(y',2);
If you don't know the number of groups, then if the points always contain the same number of pixels, you could work it out from that - in the example there are 7 pixels per point so
npts = numel(y) / 7;
y_groups = kmeans(y',npts);
We could add a loop afterwards to get the mean of each group (there are many other ways you could look into for this too e.g. grpstats):
y_means = NaN(npts,1);
for I = 1:npts
y_means(I) = mean(y(y_groups == I));
end

How to plot an n-points discrete segment between two given points in Matlab?

Given two points, what's the best way to plot - in Matlab - a n-points discrete segment that has these points as extremes?
What if I have to plot a chain of discrete segments like that?
Thank you in advance!
The following is an example of what I'm trying to achieve in the easiest possible way
Assuming your points are stored in the fashion p = [35,0; 40,0.2; 45,0], i.e.
p =
35.0000 0
40.0000 0.2000
45.0000 0
Then you can create an array for all x values by finding the mininum and maximum values of the x coordinate. Here, the x coordinate is the first column of p, i.e. p(:,1). You can use the colon operator : to create the x array by
x = min(p(:,1)) : 1 : max(p(:,1))
The 1 in the middle is the step width. For your example, this will create the array
x =
35 36 37 38 39 40 41 42 43 44 45
Now you can interpolate all y value linearly with the interp1 function. This does a linear interpolation by default. The syntax is thus
y = interp1(p(:,1), p(:,2), x)
Finally you can plot the vectors x and y using plot. If you only want to print circles, use 'o' as LineSpec specifier. To connect the circles using a line, use '-o'. There's an extensive list of options here. You can also add the color of the line / markers to this format spec. Black circles would be 'ok':
plot(x, y, 'ok')

How to find K random different pixels in an image? [duplicate]

This question already has answers here:
Randomly Selecting Pixels in a Picture Matlab
(3 answers)
Closed 7 years ago.
I know how to find a random pixel by using rand function, for both x&y in the limits of the image. Then do it K times with a loop.
However I'd like to do it in smarter way and make sure I don't pick the same
(x, y) coordinate. Thanks in advance!
Use randperm (no toolbox required):
K = 10;
[h, w, c] = size(image);
[X, Y] = ind2sub([h w], randperm(h*w, K));
The tricky part here is avoiding repetition. If you have the Statistics Toolbox you can use randsample:
k = 10;
[m,n] = size(image(:,:,1)); %// works with 3- and 1-channel images
s = randsample(m*n, k); %// get k random indices
[X, Y] = ind2sub([m, n], s); %// convert indices to x,y coordinates
On my test run with a 512x512x3 image I got the following coordinates:
X =
464 143 174 235 437 201 348 272 212 260
Y =
499 449 508 148 107 114 341 196 60 224
randi generates integers between 1 and a specified limit, you can use that with your image size to generate pixel coordinates. To make sure you don't pick the same coordinates again maintain a matrix of logicals and mark pixels you are picking.
If you just want to pick K random pixels from the image I would suggest use something like randi(imgSize,K,2) to generate a matrix of indices. You could end up with duplicates in the matrix and to eliminate those you can use unique with the 'rows' argument.

conversion between RGB and HSV space

I am currently trying to convert two objects from RGB space to HSV space using the rgb2hsv function, one being an image, the other being a matrix of RGB values, but my results for the value part of the matrix are not consistent.
The results for value in matrix I are between 1 and 255, but in the second matrix D, they are between 0 and 1. Does anybody know why this is the case?
I = imread('00000001.jpg');
I = rgb2hsv(I);
D = [221 12 26; 30 68 76; 40 47 27; 165 87 25; 37 59 26; 148 125 91];
D = rgb2hsv(D);
When you call rgb2hsv with a N-by-3 matrix, it is interpreted as a colormap, not an image or even image intensities. A colormap has values on [0,1], while a uint8 image has values on [0,255]. This is what rgb2hsv expects.
The colormap syntax explained by the help page for rgb2hsv:
H = rgb2hsv(M) converts an RGB color map to an HSV color map.
Each map is a matrix with any number of rows, exactly three columns,
and elements in the interval 0 to 1.
When you run D = rgb2hsv(D); it is running it with the above syntax, rather than treating the input as an image.
That said, you can just divide the third column of the output D by 255 since the resulting bizarro colormap seems to simply have scaled value elements.
I simply multiplied by 255 on the resulting matrix from running rgb2hsv on an image. I verified that the hue, saturation, and value were then the correct value and it was. This solved my problem. Be sure to verify. Another weird thing was that those values are a percentage, so 1 means 100% and 0.5 means 50%. This also threw me off.

Scan through an image for a specific point in a matrix in MATLAB

I have an image of size 480 (height) by 640 (width). I also have a matrix of size [1 x 280]. These 280 values are points which can be found in the image.
I would like to find out what are the points from the matrix that can be found in a particular section of the image. I did a nested for loop to specify the location where I want to scan to search for the points, but I have trouble doing the "scanning".
% matrixC = [435 560 424 132 453 ........ 596] for example of size 280
for height = 1:480
for width = 635:640
W = C(max);
end
end
This it only displays W as the greatest value of C, but I need to only show the greatest value of C within the sections of between 1 and 480 for the height, and 635 to 640 for the width. How do I write code to only scan the particular section I am interested in, and if there are, like, 10 numbers found within that section, how do I select them?
You can use ismember and direct indexing in the image matrix to get a binary matrix of "is" or "is-not" values.
imageC = randi(256, 480, 640); % random image
vectorW = randi(256, 1, 280); % random vector of points
imagePart = imageC(1:480, 635:640); % select section by indexing
imageMember = ismember(imagePart, vectorW); % check membership
Update (changing vectorW to C, adding handling for 3-channel image, and actual point value return): You can apply your own image imageC and vector C on the following by replacing first two lines.
imageC = randi(256, 480, 640, 3); % (random) image [480 x 640 x 3]
C = randi(256, 1, 280); % (random) vector of points [1 x 280]
imagePart = imageC(1:480, 635:640, :); % select section by indexing [480 x 6 x 3]
imageMember = ismember(imagePart, C); % check membership [480 x 6 x 3]
pointsInImage = unique(imagePart(imageMember)); % unique set of points from C found in imagePart