我正在尝试使用MATLAB识别图片中每个值的匹配和硬币数量。 这是起始图片,带有匹配和4种不同的硬币值。 (5小银,2小金,2大银,4大金币)
输出: 这是代码:
close all;
img = (imread('C:\Users\Torstein\Jottacloud\Skole\Visu\Prosjekt\sample_images\sample2.jpg'));
img_gray = rgb2gray(img);
% Filter image for easier edge detection
m = 12;
n = 12;
img_filter = imfilter(img_gray, fspecial('average', [m n]));
%figure, imshow(f), title('f')
% Edge detection
[~, threshold] = edge(img_filter, 'canny');
fudgeFactor = 1.5;
img_edge = edge(img_filter, 'canny', threshold * fudgeFactor);
figure, imshow(img_edge), title('edge detection')
% Dilate image to make the coin edges complete without holes
se_disk = strel('disk',4);
se_line1 = strel('line',3,100);
se_line2 = strel('line',3,100);
img_dilated = imdilate(img_edge, se_disk);
img_dilated = imdilate(img_dilated, [se_line1 se_line2]);
figure, imshow(img_dilated), title('dilate')
% Remove small objects (noise) and fill complete objects
img_clearborder = imclearborder(img_dilated, 4);
%figure, imshow(BWclear), title('cleared border image');
img_fill = imfill(img_clearborder, 'holes');
figure, imshow(img_fill), title('fill holes')
% Erode image to make a clear cut between objects
se_diamond = strel('diamond',2);
img_erode = imerode(img_fill,se_diamond);
for k=1:3
img_erode = imerode(img_erode,se_diamond);
end
img_nosmall = bwareaopen(img_erode,300);
figure, imshow(img_nosmall), title('erode')
[B, L] = bwboundaries(img_nosmall);
figure, imshow(label2rgb(L, @jet, [.5 .5 .5])), title('boundaries')
hold on
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'w', 'LineWidth', 2)
end
stats = regionprops(L,img(:,:,1),...
'Area','Centroid','Orientation','EquivDiameter','MeanIntensity');
threshold = 0.80; % For differentiating coins from matches based on an objects circularity
coinCentroids = [];
coinIntensities = [];
matchCentroids = [];
matchAngles = [];
coinRatios = [];
for k = 1:length(B)
boundary = B{k};
delta_sq = diff(boundary).^2;
perimeter = sum(sqrt(sum(delta_sq,2)));
area = stats(k).Area;
metric = 4*pi*area/perimeter^2;
metric_string = sprintf('%2.2f',metric);
angle_string = sprintf('%2.2f',stats(k).Orientation);
centroid = stats(k).Centroid;
if metric > threshold
% Object is round, therefore a coin
coinCentroids = [coinCentroids; centroid];
coinIntensities = [coinIntensities; stats(k).MeanIntensity];
coinRatios = [coinRatios; stats(k).EquivDiameter/area];
else
% Object is a match
angle = stats(k).Orientation;
matchCentroids = [matchCentroids; centroid];
matchAngles = [matchAngles; angle];
end
plot(centroid(1),centroid(2),'ko');
% text(boundary(1,2)-35,boundary(1,1)+13,angle_string,'Color','y',...
% 'FontSize',14,'FontWeight','bold');
end
正如您所看到的,我已经确定哪些对象是硬币以及哪些对象是匹配的。 但是,我很难确定硬币的价值。
例如,硬币的面积/直径给出以下结果。我完全没有看到根据这些数据区分不同类型硬币的明确方法;数字太近了。
0.0041 0.0042 0.0043 0.0043 0.0044 0.0045 0.0048 0.0048 0.0053 0.0054 0.0055 0.0055 0.0056
我尝试从每枚硬币的起始图片中获得平均颜色强度,但这并没有帮助我将银色硬币与金色硬币分开。
红色通道的平均强度没有提供6个金色硬币和6个银色硬币的信息。
105.0104
105.4408
107.9070
112.4762
116.3412
127.3481
132.1418
137.9697
149.6601
159.2506
167.6910
181.1673
215.0395
问题:如何识别不同的硬币值?
(在这里询问如何分开两个连接的对象:Separate two overlapping circles in an image using MATLAB)
由于
答案 0 :(得分:1)
首先,regionprops 'BoundingBox'
,我使用imcrop
和已识别硬币的BoundingBox从起始图片中剪下硬币的图片。
然后,使用imfindcircles
我可以检测到银色硬币中的洞。最后,我使用硬币区域识别硬币值。
最终代码:
close all;
img = (imread('C:\Users\Torstein\Jottacloud\Skole\Visu\Prosjekt\sample_images\sample1.jpg'));
%figure, imshow(img);
img_gray = rgb2gray(img);
% img_hsv = rgb2hsv(img);
% imgv = img_hsv(:,:,3);
% [Gx, Gy] = imgradientxy(imgv);
% [Gmag, Gdir] = imgradient(Gx, Gy);
% Gmag could be useful
% Filter image for easier edge detection
m = 12;
n = 12;
img_filter = imfilter(img_gray, fspecial('average', [m n]));
%figure, imshow(f), title('f')
% Edge detection
[~, threshold] = edge(img_filter, 'canny');
fudgeFactor = 1.5;
img_edge = edge(img_filter, 'canny', threshold * fudgeFactor);
%figure, imshow(img_edge), title('edge detection')
% Dilate image to make the coin edges complete without holes
se_disk = strel('disk',4);
se_line1 = strel('line',3,100);
se_line2 = strel('line',3,100);
img_dilated = imdilate(img_edge, se_disk);
img_dilated = imdilate(img_dilated, [se_line1 se_line2]);
%figure, imshow(img_dilated), title('dilate')
% Remove stuff touching the image border and fill complete objects
img_clearborder = imclearborder(img_dilated, 4);
%figure, imshow(BWclear), title('cleared border image');
img_fill = imfill(img_clearborder, 'holes');
%figure, imshow(img_fill), title('fill holes')
% Erode image to make a clear cut between objects
se_diamond = strel('diamond',2);
img_erode = imerode(img_fill,se_diamond);
for k=1:3
img_erode = imerode(img_erode,se_diamond);
end
img_nosmall = bwareaopen(img_erode,300); % Remove small objects (noise)
%figure, imshow(img_nosmall), title('erode')
[B, L] = bwboundaries(img_nosmall);
%figure, imshow(label2rgb(L, @jet, [.5 .5 .5])), title('boundaries')
% hold on
% for k = 1:length(B)
% boundary = B{k};
% plot(boundary(:,2), boundary(:,1), 'w', 'LineWidth', 2)
% end
stats = regionprops(L,img(:,:,1),...
'Area','Centroid','Orientation','EquivDiameter','Image','BoundingBox');
threshold = 0.80; % For differentiating coins from matches based on an objects circularity
coinCentroids = [];
coinTypes = []; % 0 for Silver, 1 for Gold
coinValues = []; % 1, 5, 10 eller 20 kroning
coinAreas = [];
silverCoinAreas = [];
goldCoinAreas = [];
matchCentroids = [];
matchAngles = [];
radiusRange = [8,40];
for k = 1:length(B)
boundary = B{k};
delta_sq = diff(boundary).^2;
perimeter = sum(sqrt(sum(delta_sq,2)));
area = stats(k).Area;
metric = 4*pi*area/perimeter^2;
metric_string = sprintf('%2.2f',metric);
angle_string = sprintf('%2.2f',stats(k).Orientation);
centroid = stats(k).Centroid;
if metric > threshold
% Object is round, therefore a coin
coinValues = [coinValues; 0];
coinAreas = [coinAreas; area];
coinCentroids = [coinCentroids; centroid];
bbox = stats(k).BoundingBox;
im = imcrop(img,bbox);
%figure, imshow(im);
[centers,radii] = imfindcircles(im,radiusRange,'ObjectPolarity','bright');
%viscircles(centers,radii);
if length(centers) > 0
% Coin has a hole, therefore either 1-kroning or 5-kroning
coinTypes = [coinTypes; 0];
silverCoinAreas = [silverCoinAreas; area];
else
% Coin does not have hole, therefore either 10-kroning or
% 20-kroning
coinTypes = [coinTypes; 1];
goldCoinAreas = [goldCoinAreas; area];
end
else
% Object is a match
angle = stats(k).Orientation;
matchCentroids = [matchCentroids; centroid];
matchAngles = [matchAngles; angle];
end
%plot(centroid(1),centroid(2),'ko');
% text(boundary(1,2)-35,boundary(1,1)+13,angle_string,'Color','y',...
% 'FontSize',14,'FontWeight','bold');
end
goldThreshold = 0.1;
silverThreshold = 0.1;
maxSilver = max(silverCoinAreas);
maxGold = max(goldCoinAreas);
for k=1:length(coinTypes)
area = coinAreas(k);
if coinTypes(k) == 0
if area >= maxSilver-maxSilver*silverThreshold
% 5-kroning
coinValues(k) = 5;
else
% 1-kroning
coinValues(k) = 1;
end
else
if area >= maxGold-maxGold*goldThreshold
% 20-kroning
coinValues(k) = 20;
else
% 10-kroning
coinValues(k) = 10;
end
end
end
% OUTPUT:
coinCentroids
coinValues
matchCentroids
matchAngles
由于