I am using the following code in MATLAB to find the rectangle containing a car's license plate:
clc
clear
close all
%Open Image
I = imread('plate_1.jpg');
figure, imshow(I);
%Gray Image
Ib = rgb2gray(I);
figure,
subplot(1,2,1), imshow(Ib);
%Enhancement
Ih = histeq(Ib);
subplot(1,2,2), imshow(Ih);
figure,
subplot(1,2,1), imhist(Ib);
subplot(1,2,2), imhist(Ih);
%Edge Detection
Ie = edge(Ih, 'sobel');
figure,
subplot(1,2,1), imshow(Ie);
%Dilation
Id = imdilate(Ie, strel('diamond', 1));
subplot(1,2,2), imshow(Id);
%Fill
If = imfill(Id, 'holes');
figure, imshow(If);
%Find Plate
[lab, n] = bwlabel(If);
regions = regionprops(lab, 'All');
regionsCount = size(regions, 1) ;
for i = 1:regionsCount
region = regions(i);
RectangleOfChoice = region.BoundingBox;
PlateExtent = region.Extent;
PlateStartX = fix(RectangleOfChoice(1));
PlateStartY = fix(RectangleOfChoice(2));
PlateWidth = fix(RectangleOfChoice(3));
PlateHeight = fix(RectangleOfChoice(4));
if PlateWidth >= PlateHeight*3 && PlateExtent >= 0.7
im2 = imcrop(I, RectangleOfChoice);
figure, imshow(im2);
end
end
Plates all have white backgrounds. Currently,I use the rectangles' ratio of width to height to select candidate regions for output. This gives the plate rectangle in addition to several other irrelevant ones in the case of a white car. What method can I use to get only one output: the license plate?
Also, I don't find a plate at all when I run the code on a black car. Maybe that's because the car's color is the same as the plate edge.
Are there any alternatives to edge detection to avoid this problem?
Try this !!!
I = imread('http://8pic.ir/images/88146564605446812704.jpg');
im=rgb2gray(I);
sigma=1;
f=zeros(128,128);
f(32:96,32:96)=255;
[g3, t3]=edge(im, 'canny', [0.04 0.10], sigma);
se=strel('rectangle', [1 1]);
BWimage=imerode(g3,se);
gg = imclearborder(BWimage,8);
bw = bwareaopen(gg,200);
gg1 = imclearborder(bw,26);
imshow(gg1);
%Dilation
Id = imdilate(gg1, strel('diamond', 1));
imshow(Id);
%Fill
If = imfill(Id, 'holes');
imshow(If);
%Find Plate
[lab, n] = bwlabel(If);
regions = regionprops(lab, 'All');
regionsCount = size(regions, 1) ;
for i = 1:regionsCount
region = regions(i);
RectangleOfChoice = region.BoundingBox;
PlateExtent = region.Extent;
PlateStartX = fix(RectangleOfChoice(1));
PlateStartY = fix(RectangleOfChoice(2));
PlateWidth = fix(RectangleOfChoice(3));
PlateHeight = fix(RectangleOfChoice(4));
if PlateWidth >= PlateHeight*1 && PlateExtent >= 0.7
im2 = imcrop(I, RectangleOfChoice);
%figure, imshow(I);
figure, imshow(im2);
end
end
Related
I've to plot multiple scatter and table in a grid space and I'm having a couple of issues with the relative position but most important with defining and maintaining the aspect ratio of the scatter plot.
I've written a script with "fake" data on it to describe my problem and a minimum "not working" example below.
What I have is a dataframe with x, and y positions of objects, and what I want to do is to put the corresponding image below.
Since the image can have an arbitrary aspect ratio I need to read the aspect ratio and construct the scatter plot in that way but I'm unable to make it work.
Another problem is connected with the invert_xaxis and invert_yaxis that don't work (I need that command since the scatter data are inverted.
I've used the following commands, and as far as I've understood each of them should block the aspect ratio of the scatter plot to the same ratio of the figure but they do not work.
The aspect ratio becomes corrected only when the figure is plotted but that eliminates the effect of axis inversion.
I've had a similar problem with setting the aspect ratio of plots without the addition of a figure, sometimes it worked but not with tight_layout.
It is obvious that I'm missing something important....but I'm unable to figure it out.
This is the fake data code:
###############################################################################
# fake data
#general data aspect ratio
image_height= 5 #4270
image_width = 10 # 8192
pix2scale = 0.3125
data_AR = image_height / image_width
#random data generation
data_width = image_width* pix2scale
data_height = image_height * pix2scale
data1x = np.random.uniform(-data_width/2, data_width/2, size=(40))
data1y = np.random.uniform(-data_height/2, data_height/2, size=(40))
data2x = np.random.uniform(-data_width/2, data_width/2, size=(40))
data2y = np.random.uniform(-data_height/2,data_height/2, size=(40))
temp_df1 = pd.DataFrame([data1x,data1y,['random1']*40],index = ['x','y','label']).T
temp_df2 = pd.DataFrame([data2x,data2y,['random2']*40],index = ['x','y','label']).T
df = pd.concat([temp_df1,temp_df2],axis = 0, ignore_index = True)
del temp_df1, temp_df2
#sample image generation of variable aspect ratio
img_size = (image_height, image_width)
R_layer = np.ones(shape= img_size)*0.50
G_layer = np.ones(shape= img_size)*0.50
B_layer = np.ones(shape= img_size)*0.50
A_layer = np.ones(shape= img_size)
img = np.dstack([R_layer,G_layer,B_layer,A_layer])
#add a mark at the top left of the image
for k in range(0,3):
for i in range(0,int(image_width*0.2*data_AR)):
for j in range(0,int(image_width*0.2)):
img[i,j,k] = 0
#add a mark at the center of the image
# get center coordinates of the image
center = [[2, 4], [2, 5]]
for k in range(0,3):
for point in center:
if k == 0:
img[point[0],point[1],k] = 1
else:
img[point[0],point[1],k] = 0
#show image
fig, ax = plt.subplots()
ax.imshow(img)
###############################################################################
this is the code that generates the image:
#%%
# sample code
# at this point IƬve already loaded the image, the pix2scale value
# and the df containing data points
#read image aspect ratio
img_AR = img.shape[0]/img.shape[1]
pixel_width = img.shape[1]
pixel_height = img.shape[0]
# each pixel correspond to 0.3125 unit (mm)
pix2scale = 0.3125
#define image position
#the center of the image need to be placed at (0,0)
#bottom left corner
left = - (pixel_width * pix2scale)/2
bottom = - (pixel_height * pix2scale)/2
right = left + (pixel_width * pix2scale)
top = bottom + (pixel_height * pix2scale)
extent = [left,right,bottom,top]
#figure definition
figure_width = 15 #inch
figure_AR = 1
scatter_AR = img_AR
#initialize figure
fig_s= plt.figure(figsize = (figure_width,figure_width*figure_AR))
gs = plt.GridSpec (3,3)
#scatter plot in ax1
ax1 = fig_s.add_subplot(gs[:2,:2])
g = sns.scatterplot( data = df,
x = 'x',
y = 'y',
hue = 'label',
ax =ax1
)
ax1.invert_xaxis()
ax1.invert_yaxis()
#resize the figure box
box = ax1.get_position()
ax1.set_position([box.x0,box.y0,box.width*0.4,box.width*0.4*scatter_AR])
ax1.legend(loc = 'center left', bbox_to_anchor = (1,0.5))
ax1.set_title('Inclusions Scatter Plot')
ax1.set_aspect(scatter_AR)
#plt image
ax1.imshow(img,extent = extent)
#scatter plot
ax2 = fig_s.add_subplot(gs[2,:2])
g = sns.scatterplot( data = df,
x = 'x',
y = 'y',
hue = 'label',
ax =ax2
)
#resize the figure box
box = ax2.get_position()
ax2.set_position([box.x0,box.y0,box.width*0.4,box.width*0.4*scatter_AR])
ax2.legend(loc = 'center left', bbox_to_anchor = (1,0.5))
ax2.set_title('Inclusions Scatter Plot')
ax2.set_aspect(scatter_AR)
ax2.imshow(img,extent = extent)
#scatter plot
ax3 = fig_s.add_subplot(gs[1,2])
g = sns.scatterplot( data = df,
x = 'x',
y = 'y',
hue = 'label',
ax =ax3
)
#resize the figure box
box = ax3.get_position()
ax3.set_position([box.x0,box.y0,box.width*0.4,box.width*0.4*scatter_AR])
ax3.legend(loc = 'center left', bbox_to_anchor = (1,0.5))
ax3.set_title('Inclusions Scatter Plot')
ax3.set_aspect(scatter_AR)
ax3.imshow(img,extent = extent)
#add suptitle to figure
fig_s.suptitle('my title',fontsize= 22)
fig_s.subplots_adjust(top=0.85)
# #make it fancy
for i in range(3):
fig_s.tight_layout()
plt.pause(0.2)
I've plotted multiple grid because I wanted to test the tight_layout().
[enter image description here][2]
I am currently doing a project on morphology of filamentous fungi during batch fermentation (Yes, I am not a software engineer.. Biotech). Where I am taken pictures of the morphology in a petri dish. I am developing a "fast" method to describe the pellets (small aggregates of fungi) that occurs during the fermentation. To do this I am writing a code in MatLab.
Depending on the color of the pellets (light or dark) the pictures are taken on differen backgrounds, black or white. I am inverting the picture if the mean gray value is below 70 to distinguish between backgrounds.
Pictures:
White background
Dark background
I have several problems:
Detecting the edge of the petri dish so it won't be regarded as an object (Currently done with the edge('log',) function). The edge is detected, but i miss some parts, think because of the lower light in top.
Proper thresholding inside the dish
Detection of pellets - right now it is done by a combination of running through each color channel, but might be done with some blob detection?
Does anybody have some inputs?
My code is as following:
close all
clear all
clc
%Empty arrays to hold data
metricD=[];
areaD=[];
perimeterD=[];
% Specify the folder where the files live.
myFolder = pwd;
% Check to make sure that folder actually exists. Warn user if it doesn't.
if ~isdir(myFolder)
errorMessage = sprintf('Error: The following folder does not exist:\n%s', myFolder);
uiwait(warndlg(errorMessage));
return;
end
% Get a list of all files in the folder with the desired file name pattern.
filePattern = fullfile(myFolder, '*.jpg'); % Change to whatever pattern you need.
theFiles = dir(filePattern);
% Show debugging plots
plotFig = 0;
% parameters that can be tuned
% how many colors channels we minimum want to see a spore in
% e.g. set to 1 for image "P. f Def C.tif"
labelcutOff = 1;
% remove areas larger than
removeLargerthan = 500000;
for k = 1 : length(theFiles)
baseFileName = theFiles(k).name;
fullFileName = fullfile(myFolder, baseFileName);
%% reading as an image array with im
I = imread(fullFileName);
% convert to grayscale
Ig = rgb2gray(I);
if plotFig
figure;imagesc(I)
figure;imagesc(Ig)
end
mm=mean(mean(Ig));
if mm < 70
I=imcomplement(I);
Ig = imcomplement(Ig);
end
% BLOB DETCTION
% h = fspecial('log', [15 15], 2);
% imLOG = imfilter(Ig, h);
% figure;imagesc(imLOG)
%% find petridish by edges and binary operations
% HACK - NOT HOW IT SHOULD BE DONE
Ig = wiener2(Ig,[5 5]);
imEdge = edge(Ig,'log');
circle = bwareaopen(imEdge,50);
circle = imclose(circle,strel('disk',30));
circle = bwareaopen(circle,8000);
% circle = imfill(circle,'holes');
circle = bwconvhull(circle);
circle = imerode(circle,strel('disk',150));
if plotFig
figure;imagesc(circle)
end
%% Get thresholds inside dish using otsu on each channel
imR = double(I(:,:,1)) .* circle;
imG = double(I(:,:,2)) .* circle;
imB = double(I(:,:,3)) .* circle;
thresR = graythresh(uint8(imR(circle))) *max(imR(circle));
thresG = graythresh(uint8(imG(circle))) *max(imG(circle));
thresB = graythresh(uint8(imB(circle))) *max(imB(circle));
if plotFig
figure;imagesc(imR)
figure;imagesc(imG)
figure;imagesc(imB)
end
%% classify inside dish
% check if it should be smaller or larger than
if sum(imR(circle) < thresR) > sum(imR(circle) > thresR)
labelR = imR > thresR;
else
labelR = imR < thresR;
end
if sum(imG(circle) < thresG) > sum(imG(circle) > thresG)
labelG = imG > thresG;
else
labelG = imG < thresG;
end
if sum(imB(circle) < thresB) > sum(imB(circle) > thresB)
labelB = imB > thresB;
else
labelB = imB < thresB;
end
if plotFig
figure;imagesc(labelR)
figure;imagesc(labelG)
figure;imagesc(labelB)
end
labels = (labelR + labelG + labelB) .* circle;
labels(labels < labelcutOff) = 0;
labels = imfill(labels,'holes');
labels = bwareaopen(labels,30);
if plotFig
figure;imagesc(labels)
end
%% clean up labels
labelBig = bwareaopen(labels,removeLargerthan);
labels = labels - labelBig;
if plotFig
figure;imagesc(labels)
end
BN = labels;
%% old script
stats = regionprops(BN,'Basic');
obj2 = numel(stats);
[B,L] = bwboundaries(BN,'holes');
figure
% imshow(label2rgb(L, #jet, [.5 .5 .5]))
imshow(I)
hold on
title(baseFileName)
for j = 1:length(B)
boundary = B{j};
plot(boundary(:,2), boundary(:,1),'w','LineWidth',2)
end
%region stats
stats = regionprops(L,'Area','Centroid');
%Threshold for printing in end
threshold = 0.2;
%Conversion factor pixel to cm
conversionF=9/2125;
% loop over the boundaries
for j = 1:length(B)
% obtain (X,Y) boundary coordinates corresponding to label 'j'
boundary = B{j};
% compute a simple estimate of the object's perimeter
delta_sq = diff(boundary).^2;
perimeter = sum(sqrt(sum(delta_sq,2)));
perimeterD(j,k)=perimeter*conversionF;
% obtain the area calculation corresponding to label 'k'
area = stats(j).Area;
areaD(j,k)=area*conversionF^2;
% compute the roundness metric
metric = 4*pi*area/perimeter^2;
metricD(j,k)=metric;
% display the results
metric_string = sprintf('%d. %2.2f', j,metric);
text(boundary(1,2)-50,boundary(1,1)+23,metric_string,'Color','k',...
'FontSize',14,'FontWeight','bold');
end
drawnow; % Force display to update immediately.
end
%Calculating stats
areaM=mean(areaD);
pM=mean(perimeterD);
metricD(metricD==Inf)=0;
mM=mean(metricD);
Hint:
A morphological top-hat filter fllowed by binarization (with a constant threshold ?) can be a good start. And filtering on the blob size will do a reasonable cleanup.
For the edges, try circular Hough.
I have lena image in Matlab. First I need to find the centroid C, and then divide the image into equal number of parts. I can calculate the centroid of the image but from that how can I divide the image into equal number of parts as shown below. Please anyone help me.
Thanks
Using poly2mask to create binary sectors and using the resulting sectors for indexing
Code:
im = imread('peppers.png');
r = 300;
out1 = ones(max(size(im,1),r*2)+2,max(size(im,2),r*2)+2,3).*255;
xoffset = floor((size(out1,2)-size(im,2))/2);
yoffset = floor((size(out1,1)-size(im,1))/2);
out1(yoffset:yoffset+size(im,1)-1,xoffset:xoffset+size(im,2)-1,:) = im(:,:,:);
im = out1;
cy = floor(size(im,1)/2);
cx = floor(size(im,2)/2);
figure;
imshow(uint8(im));
hold on
pos = [cx-r+1 cy-r+1 r*2 r*2];
rectangle('Position',pos,'Curvature',[1 1]);
x1 = [-r, 0, -r*cosd(45), -r*cosd(45); r, 0, r*cosd(45), r*cosd(45)]+cx+1;
y1 = [0, -r, -r*sind(45), r*sind(45); 0, r, r*sind(45), -r*sind(45)]+cy+1;
plot(x1,y1);
hold off
figure;
for i = 0:45:315
t = linspace(-i,-i-45,128);
x = [cx, cx+r*cosd(t), cx];
y = [cy, cy+r*sind(t), cy];
bw = poly2mask( x, y, size(im,1),size(im,2));
bw = repmat(bw,1,1,3);
out = ones(size(im,1),size(im,2),size(im,3)).*155;
out(bw) = im(bw);
subplot(2,4,(i/45)+1); imshow(uint8(out));
end;
Results:
Original Image
Partitions drawn over Original Image
Segments of the image
Update
for getting pixel values of the lines, by using Bresenham function from here
figure;
bw1 = zeros(size(im,1),size(im,2));
outmat = zeros(size(bw1));
[X,Y] = bresenham(cx+1-r,cy+1,cx+1+r,cy+1);
ind = sub2ind(size(outmat), Y, X);
outmat(ind) = 1;
[X,Y] = bresenham(cx+1,cy+1-r,cx+1,cy+1+r);
ind = sub2ind(size(outmat), Y, X);
outmat(ind) = 1;
[X,Y] = bresenham(cx+1-r*cosd(45),cy+1-r*sind(45),cx+1+r*cosd(45),cy+1+r*sind(45));
ind = sub2ind(size(outmat), Y, X);
outmat(ind) = 1;
[X,Y] = bresenham(cx+1-r*cosd(45),cy+1+r*sind(45),cx+1+r*cosd(45),cy+1-r*sind(45));
ind = sub2ind(size(outmat), Y, X);
outmat(ind) = 1;
se = strel('disk',5); %// change the '5' value to affect thickness of the line
outmat = imdilate(outmat,se);
outmat = repmat(boolean(outmat),1,1,3);
outmat1 = zeros(size(outmat));
outmat1(outmat) = im(outmat);
imshow(uint8(outmat1));
Pixel values under each lines
Check the following code. I just did it for a grayscale image. You can now change it to a color image as well. Check and pls confirm this is what you wanted.
clear all;
i = rgb2gray(imread('hestain.png'));
imshow(i);
cr = floor(size(i,1)/2);
cl = floor(size(i,2)/2);
r = min(cr, cl);
a = 90;
r1 = cr;
c1 = size(i,2);
v1=[c1 r1]-[cl cr];
i2 = zeros(size(i,1),size(i,2),ceil(360/a));
for ri = 1:size(i,1)
for ci = 1:size(i,2)
v2=[ci ri]-[cl cr];
a2 = mod(-atan2(v1(1)*v2(2)-v1(2)*v2(1), v1*v2'), 2*pi) * 180/pi;
d2 = pdist([ci ri; cl cr],'euclidean');
if d2<=r
if ceil(a2/a)==0
a2 =1;
end
i2(ri,ci,ceil(a2/a)) = i(ri,ci);
end
end
end
figure;
for i=1:360/a
subplot(2,180/a,i);
imshow(mat2gray(i2(:,:,i)));
end
Sample output:
I'm using normxcorr2 to find the area that exactly match with my pattern and i also want to find the other area(in the red rectangle) that is look like the pattern. I think it will be works if i can find the next maximum and so on and that value must not in the first maximum area or the first one that it has been detected but i can't do it. Or if you have any idea that using normxcorr2 to find the others area please advise me, I don't have any idea at all.
Here's my code. I modified from this one http://www.mathworks.com/products/demos/image/cross_correlation/imreg.html
onion = imread('pattern103.jpg'); %pattern image
peppers = imread('rsz_1jib-159.jpg'); %Original image
onion = rgb2gray(onion);
peppers = rgb2gray(peppers);
%imshow(onion)
%figure, imshow(peppers)
c = normxcorr2(onion,peppers);
figure, surf(c), shading flat
% offset found by correlation
[max_c, imax] = max(abs(c(:)));
[ypeak, xpeak] = ind2sub(size(c),imax(1));
corr_offset = [(xpeak-size(onion,2))
(size(onion,1)-ypeak)]; %size of window show of max value
offset = corr_offset;
xoffset = offset(1);
yoffset = offset(2);
xbegin = round(xoffset+1); fprintf(['xbegin = ',num2str(xbegin)]);fprintf('\n');
xend = round(xoffset+ size(onion,2));fprintf(['xend = ',num2str(xbegin)]);fprintf('\n');
ybegin = round(yoffset+1);fprintf(['ybegin = ',num2str(ybegin)]);fprintf('\n');
yend = round(yoffset+size(onion,1));fprintf(['yend = ',num2str(yend)]);fprintf('\n');
% extract region from peppers and compare to onion
extracted_onion = peppers(ybegin:yend,xbegin:xend,:);
if isequal(onion,extracted_onion)
disp('pattern103.jpg was extracted from rsz_org103.jpg')
end
recovered_onion = uint8(zeros(size(peppers)));
recovered_onion(ybegin:yend,xbegin:xend,:) = onion;
figure, imshow(recovered_onion)
[m,n,p] = size(peppers);
mask = ones(m,n);
i = find(recovered_onion(:,:,1)==0);
mask(i) = .2; % try experimenting with different levels of
% transparency
% overlay images with transparency
figure, imshow(peppers(:,:,1)) % show only red plane of peppers
hold on
h = imshow(recovered_onion); % overlay recovered_onion
set(h,'AlphaData',mask)
i am able to overlap the binary image with the original RGB image. Through the following code.
inImage = imresize(imread('1.jpg'),0.25);
%imwrite(inImage,'original.jpg');
inImage = skyremoval(inImage);
greyImage = rgb2gray(inImage);
thresh1 = 200;
whiteLayer = greyImage > thresh1;
thresh2 = 125;
lightgreyLayer = greyImage > thresh2 & greyImage <= thresh1;
layer1 = whiteLayer*200;
layer2 = lightgreyLayer*125;
G = layer1 + layer2;
% figure,imshow(G);
se = strel('disk', 15);
Io = imopen(G, se);
figure,imshow(Io);
f = find(Io==0);
mask(:,:,1) = f; % For the red plane
% mask(:,:,2) = f; % For the green plane
% mask(:,:,3) = f; % For the blue plane
inImage(mask)=0;
I = inImage;
figure,imshow(I);
The following are the images.
Here.The first is the binary image derived from the original, second is the original and the third is the result after overlaping both binary and rgb images, by the code given above. As you can see the problem i am facing is that the part except road is cyan all i want is the part which is not road to be black. How can i do that?
Please alter my code if you can help. Thank you.
You don't need the find command, since you can index with a binary image.
Instead of
f = find(Io==0);
mask(:,:,1) = f; % For the red plane
% mask(:,:,2) = f; % For the green plane
% mask(:,:,3) = f; % For the blue plane
inImage(mask)=0;
I = inImage;
figure,imshow(I);
you can write
mask = repmat(Io==0,1,1,3); %# 1 wherever mask is false
I = inImage;
I(mask) = 0;
figure,imshow(I);