How to find all the blue pixels and the location of the two boundaries in blue pixels? - matlab

I want to find per column the first and last blue pixels and them find the other boundary ( first and last blue pixel rows) inside this rows achieved before.
I made the alterations based on the previous answeers, but now I have this error when it tries to find the bif_first and last: Subscripted assignment dimension mismatch. bif_first2(2,z)=find(dx(:,z)==1,2,'first');
What is wrong? Please see my code below:
rgbImage_blue=zeros(size(movingRegistered));
lumen_first=zeros(1,size(movingRegistered,2)); lumen_last=zeros(1,size(movingRegistered,2)); bif_first=zeros(1,size(movingRegistered,2)); bif_last=zeros(1,size(movingRegistered,2)); bif_last2=zeros(2,size(movingRegistered,2)); bif_first2=zeros(2,size(movingRegistered,2));
blue=cat(3,0,0,255);
ix=all(bsxfun(#eq,movingRegistered,blue),3);% find all the blue pixels, and put them at 1 % logical array of where blue pixels are dx=[zeros(1,size(movingRegistered,2));diff(ix)]; % zeros to make the same number of columns and rows % the difference by row for all columns
nTops=sum(dx==1); % the transitions to blue
nBots=sum(dx==-1); % and from blue... % see if are consistent; if not, something's not right in image
if(nTops~=nBots), error('Mismatch in Top/Bottom'),end
for z=1:1:size(movingRegistered,2);
if nTops(1,z)==2; bifurcation=false;lumen=true; %only existis two boundaries no bifurcation
lumen_first(1,z)=find(ix(:,z)==1,1,'first');
lumen_last(1,z)=find(ix(:,z)==1,1,'last');
end
if nTops(1,z)>2;
bifurcation=true;
lumen_first(1,z)=find(ix(:,z)==1,1,'first');
lumen_last(1,z)=find(ix(:,z)==1,1,'last');
bif_first2(2,z)=find(dx(:,z)==1,2,'first');
bif_first(1,z)=bif_first2(2,z);
bif_last2(2,z)=find(dx(:,z)==1,2,'last');
bif_last(1,z)=bif_last2(2,z);
end
end

Your problem is you are comparing a n*m*3 image with a 3*1 vector. This operation is not defined.
Use this code:
blue=cat(3,0,0,250)
ix=all(bsxfun(#eq,movingRegistered,blue),3)
Images in Matlab use the third dimension for color, that's why I created blue to be a 1*1*3 vector. Now this vector is compared to the image, using bsxfun to expand the vector to match the image size. This operation compares each color channel individually, so all is used to collect the data for all three channels.

Related

How to create a mask to segment a color image by activecontour?

I want to use the function activecontour in matlab to segment a color image, but I don't know how to create the mask.
The documentation says:
For color and multi-channel images, mask must be a 2-D logical array where the first two dimensions match the first two dimensions of the image A.
But I don't understand what has to be done. Any suggestions?
Let's consider that the size of your image is NxM pixels, N is the number of rows, M the number of columns.
If it is a color image, each pixel is probably composed of 3 values, one for intensity of red (R), one intensity of blue (B) and one for intensity of green (G). These are called the color channels. So the real shape of the matrix representing your image is NxMx3.
What the documentation says is that the mask should be 2-D, and the dimensions should match the first two dimension of your image. It means the mask should have the same number of rows and cols than your image, but each pixel of the mask is not composed of 3 values anymore. It is composed of 1 value (a logical value : 0 or 1).
So what you need to do is to give the function a matrix NxM with only 0 and 1 as possible values. The doc says that the mask is the :
Initial contour at which the evolution of the segmentation begins, specified as a binary image the same size as A.
So the mask needs to represent an initial guess of the contour. If you already know that what you want to see is in the upper left corner of the image, you can set the initial contour as a square located in the upper left corner for example.
Now to represent the contour by a matrix of logicals, you simply set all the elements of the matrix to 0 and just the elements representing the contour to 1 I guess.
Lets me know if there is something you don't understand, I'd be glad to answer you.

Scatter plot color thresholding

I am trying to write a script to plot florescence intensity from some microscopy data as a scatter plot and threshold this data based on cells that respond greater than a certain amount in CFPMAX and plot these in green and cells that do not in red. When I try to plot this, I am unable to really assign proper colors to points and they end up being blue and red. I need each cell in the image to be assigned 4 values, (3 values for for each florescence channel and one value to determine whether or not it responded (green or red). Thus I was wondering if it was possible to assign the proper color to the 4th column of the matrix, or if I am going about this the wrong way all together. I have attached my code below.
MCHR=csvread('data1.csv');
MYFP=csvread('data2.csv');
MCFP=csvread('data3.csv');
CFPMAX=(max(MCFP))';
MCHMAX=(max(MCHR))';
YFPMAX=(max(MYFP))';
c=zeros(length(CFPMAX));
for i=1:length(c)
if CFPMAX(i)>40
c(i)='g'; %// green responders
else
c(i)='r'; %// red non-responders
end
end
MM=horzcat(MCHMAX,YFPMAX,CFPMAX,c);
scatter(MM(:,1),MM(:,2),100,MM(:,4),'filled','MarkerEdgeColor',[0 0 0])
title('Responders vs Non-Responders ')
xlabel('[TF1]') %// x-axis label
ylabel('[TF2]') %// y-axis label
As far as I can tell from the documentation, the input parameter c (assuming scatter(x,y,a,c,...)) can be one of:
A single character specifying a colour e.g. 'g' or 'r'. But just one single scalar colouring all of you points.
A single RGB triple colouring all of your points so [1,0,0] for red or [0,1,0] for green.
A three column matrix of RGB triples. This is likely what you want. I will demonstrate this to you.
A one column matrix of numbers which will colour the points according to a colormap. This one will also work for you but less explicitly. Incidentally, I would guess that this is option that MATLAB though your vector of characters was.
So in order to create the matrix of RGB triples you can modify your code to be
c=zeros(length(CFPMAX),3);
for i = 1:length(CFPMAX)
if CFPMAX(i)>40
c(i,:)=[0,1,0]; %// green responders
else
c(i,:)=[1,0,0]; %// red non-responders
end
end
However, you could actually do away with the for-loop completely in MATLAB and construct c in a vectorized approach using logical indexing:
c=zeros(length(CFPMAX),3);
c(CFPMAX > 40, 2) = 1; %// green responders
c(CFPMAX <= 40, 1) = 1; %// red responders
This is a more idiomatic way to do this in MATLAB.

How to extract and recognize the vehicle plate number with matlab?

I want to develop a matlab program that can extract and recognize the plate number of vehicle with template matching method.
Here is my code:
function letters = PengenalanPlatMobil(citra)
%load NewTemplates
%global NewTemplates
citra=imresize(citra,[400 NaN]); % Resizing the image keeping aspect ratio same.
citra_bw=rgb2gray(citra); % Converting the RGB (color) image to gray (intensity).
citra_filt=medfilt2(citra_bw,[3 3]); % Median filtering to remove noise.
se=strel('disk',1);
citra_dilasi=imdilate(citra_filt,se); % Dilating the gray image with the structural element.
citra_eroding=imerode(citra_filt,se); % Eroding the gray image with structural element.
citra_edge_enhacement=imsubtract(citra_dilasi,citra_eroding); % Morphological Gradient for edges enhancement.
imshow(citra_edge_enhacement);
citra_edge_enhacement_double=mat2gray(double(citra_edge_enhacement)); % Converting the class to double.
citra_double_konv=conv2(citra_edge_enhacement_double,[1 1;1 1]); % Convolution of the double image f
citra_intens=imadjust(citra_double_konv,[0.5 0.7],[0 1],0.1); % Intensity scaling between the range 0 to 1.
citra_logic=logical(citra_intens); % Conversion of the class from double to binary.
% Eliminating the possible horizontal lines from the output image of regiongrow
% that could be edges of license plate.
citra_line_delete=imsubtract(citra_logic, (imerode(citra_logic,strel('line',50,0))));
% Filling all the regions of the image.
citra_fill=imfill(citra_line_delete,'holes');
% Thinning the image to ensure character isolation.
citra_thinning_eroding=imerode((bwmorph(citra_fill,'thin',1)),(strel('line',3,90)));
%Selecting all the regions that are of pixel area more than 100.
citra_final=bwareaopen(citra_thinning_eroding,125);
[labelled jml] = bwlabel(citra_final);
% Uncomment to make compitable with the previous versions of MATLAB®
% Two properties 'BoundingBox' and binary 'Image' corresponding to these
% Bounding boxes are acquired.
Iprops=regionprops(labelled,'BoundingBox','Image');
%%% OCR STEP
[letter{1:jml}]=deal([]);
[gambar{1:jml}]=deal([]);
for ii=1:jml
gambar= Iprops(ii).Image;
letter{ii}=readLetter(gambar);
% imshow(gambar);
%
end
end
but the number recognized is always wrong and too much is detected or sometimes too little.
How to fix it?
Here is the images and this one
For number plate extraction you have to follow this algorithm(I used this in my project)
1. Find Histogram variation horizontally(by using imhist)
2. Find the part of histogram where you get maximum variation and get x1 and x2 value.
3. crop that image horizontally by using value of x1 and x2.
4. Repeat same process for vertical cropping.
Explanation:
In order to remove unnecessary information from the image, it requires only edges of the image to work. For detection of the edges, we make use of a built-in MATLAB function. But first we convert the original image to grayscale image.
This grayscale image is converted to binary image by determining a threshold for different intensities in the image. After binarization only, edge detection algorithm can be used. Here we have used ‘ROBERTS’. After extensive testing, it seemed our application the best. Then to determine the region of license plate we have done horizontal and vertical edge processing. First the horizontal histogram is calculated by traversing each column of an image. The algorithm starts traversing with the second pixel from the top of each column of image matrix. The difference between second and first pixel is calculated. If the difference exceeds certain threshold, it is added to total sum of differences. It traverses until the end of the column and the total sum of differences between neighbouring pixels are calculated. At the end, a matrix of the column-wise sum is created. The same process is carried out for vertical histogram. In this case, instead of columns, rows are processed.
After calculating horizontal and vertical histogram we have calculated a threshold value which is 0.434 times of maximum horizontal histogram value. Our next step for extraction is cropping the area of interest i.e. number plate area. For cropping we first crop original image horizontally and then vertically. In horizontal cropping we process image matrix column wise and compare its horizontal histogram value with the predefined threshold value. If certain value in horizontal histogram is more than threshold we mark it as our starting point for cropping and continue until threshold value we find-less than that is our end point. In this process we get many areas which have value more than threshold so we store all starting and end point in a matrix and compare width of each area, width is calculated difference of starting and end point. After that we find set of that staring and end point which map largest width. Then we crop image horizontally by using that starting and end point. This new horizontally cropped image is processed for vertical cropping. In vertical cropping we use same threshold comparison method but only difference is that this time we process image matrix row wise and compare threshold value with vertical histogram values. Again we get different sets of vertical start and end point again we find that set which map largest height and crop image by using that vertical start and end point. After vertical and horizontal cropping we get exact area of number plate from original image in RGB format.
For Recognition use template matching with correlation(using corr2() in matlab)
I would change the loop following character detection to
[gambar{1:jml}]=deal([]);
for ii=1:jml
gambar{ii}= Iprops(ii).Image;
%letter{ii}=readLetter(gambar);
imshow(gambar{ii});
end
I think what you want to do at this point is either
(1) pick the roi in advance before applying character extraction and ocr.
or
(2) apply ocr to all of the characters from the entire image and then use proximity rules or other rules to identify the license plate number.
Edit:
If you run the following loop after character extraction you can get an idea what I mean by "proximity":
[xn yn]=size(citra); % <-- citra is the original image matrix
figure, hold on
[gambar{1:jml}]=deal([]);
for ii=1:jml
gambar{ii}= double(Iprops(ii).Image)*255;
bb=Iprops(ii).BoundingBox;
image([bb(1) bb(1)+bb(3)],[yn-bb(2) yn-bb(2)-bb(4)],gambar{ii});
end
Here is the image after edge detection:
and after character extraction (after running the loop above):

Matlab - Replace successive pixel with pixel from the left

So, I've quantized a grayscale image with four quantized values. I'm trying to maintain the first pixel of each row of the quantized image and replace each successive pixel with the difference from the pixel to its left.
How would you code this in matlab and can someone explain this to me conceptually?
Also, my concern is that because the image is relatively uniform because of the quantization of the dynamic range, most of the image would appear black, no? It seems to me that only the transition areas and the edges will have some difference in quantized values.
To create the difference to the pixel on the left, all you have to do is subtract the pixels in columns 1,2,3... from the columns 2,3,4...
%# create a random image with four values
randomImage = randi(4,[100,90]); %# use different numbers of rows and cols so we know which is which
%# catenate the first column of the image with the difference from the pixel to the left
%# for all pairs of columns in the image
differenceImage = [randomImage(:,1),randomImage(:,1:end-1)-randomImage(:,2:end)];
Yes, you'd expect quite a few uniform patches (which will be gray, since unless you plot the absolute value of the differences, there will be some that are negative).

MATLAB: Return array of values between two co-ordinates in a large matrix (diagonally)

If I explain why, this might make more sense
I have a logical matrix (103x3488) output of a photo of a measuring staff having been run through edge detect (1=edge, 0=noedge). Aim- to calculate the distance in pixels between the graduations on the staff. Problem, staff sags in the middle.
Idea: User inputs co-ordinates (using ginput or something) of each end of staff and the midpoint of the sag, then if the edges between these points can be extracted into arrays I can easily find the locations of the edges.
Any way of extracting an array from a matrix in this manner?
Also open to other ideas, only been using matlab for a month, so most functions are unknown to me.
edit:
Link to image
It shows a small area of the matrix, so in this example 1 and 2 are the points I want to sample between, and I'd want to return the points that occur along the red line.
Cheers
Try this
dat=imread('83zlP.png');
figure(1)
pcolor(double(dat))
shading flat
axis equal
% get the line ends
gi=floor(ginput(2))
x=gi(:,1);
y=gi(:,2);
xl=min(x):max(x); % line pixel x coords
yl=floor(interp1(x,y,xl)); % line pixel y coords
pdat=nan(length(xl),1);
for i=1:length(xl)
pdat(i)=dat(yl(i),xl(i));
end
figure(2)
plot(1:length(xl),pdat)
peaks=find(pdat>40); % threshhold for peak detection
bigpeak=peaks(diff(peaks)>10); % threshold for selecting only edge of peak
hold all
plot(xl(bigpeak),pdat(bigpeak),'x')
meanspacex=mean(diff(xl(bigpeak)));
meanspacey=mean(diff(yl(bigpeak)));
meanspace=sqrt(meanspacex^2+meanspacey^2);
The matrix pdat gives the pixels along the line you have selected. The meanspace is edge spacing in pixel units. The thresholds might need fiddling with, depending on the image.
After seeing the image, I'm not sure where the "sagging" you're referring to is taking place. The image is rotated, but you can fix that using imrotate. The degree to which it needs to be rotated should be easy enough; just input the coordinates A and B and use the inverse tangent to find the angle offset from 0 degrees.
Regarding the points, once it's aligned straight, all you need to do is specify a row in the image matrix (it would be a 1 x 3448 vector) and use find to get non-zero vector indexes. As the rotate function may have interpolated the pixels somewhat, you may get more than one index per "line", but they'll be identifiable as being consecutive numbers, and you can just average them to get an approximate value.