ハフ変換を使用してグレースケール画像の円を検出するためのMATLABコードを作成しました。実行時間をできるだけ最小限に抑えたいと思います。
私が使用しているエッジ検出はカスタム実装ですが、その実行時間は必要なものに対して十分に高速です(約0.06秒)。ただし、ボトルネックは残りのコードです(合計実行時間は約6.35秒です)。ところで、私はtic/tocを使用して実行時間を計算しました。
ここにコードがあります、誰かが見ていただければ本当にありがたいです:
function [ circles ] = findCircles(img)
% set low and high bounds for radii values
minR = 9;
[imgRows, imgCols] = size(img);
maxR = ceil(min(imgRows, imgCols)/2);
tic
% run edge detection on image
edgeImg = edgeDetect(img);
% get image size
[rows, cols] = size(edgeImg);
% initialize accumulator
houghAcc = zeros(rows, cols, maxR);
% get all edge pixels from image
edges = find(edgeImg);
% find number of edge pixels
edgeNum = size(edges);
% scan each edge
for currEdge = 1 : edgeNum
% get current edge x and y coordinations
[edgeY edgeX] = ind2sub([rows, cols], edges(currEdge));
% scan each all possible radii
for r = minR : maxR
% go over all possible 2*pi*r circle centers
for ang = 0 : 360
t = (ang * pi) / 180;
cX = round(edgeX - r*cos(t));
cY = round(edgeY - r*sin(t));
% check if center found is within image boundaries
if ( cX < cols && cX > 0 && cY < rows && cY > 0 )
% found circle with (cX,cY) as center and r as radius
houghAcc(cY,cX,r)=houghAcc(cY,cX,r)+1; % increment matching counter
end
end
end
end
% initialize circle list
circles = [];
% intialize index for next found circle
nextCircleIndx = 1;
% get counter list dimensions
[sizeX sizeY sizeR] = size(houghAcc);
% get max counter value from hough counter matrix
m = max(max(max(houghAcc)));
% calculate the minimal pixels that circle should have on perimeter
t = m * 0.42;
% scan each found circle
for cX = 1 : sizeX
for cY = 1 : sizeY
for r = 1 : sizeR
% threshold values
if houghAcc(cX, cY, r) > t
% circle is dominant enough, add it
circles(nextCircleIndx,:) = [cY , cX , r ,houghAcc(cX, cY, r)];
% increment index
nextCircleIndx = nextCircleIndx + 1;
end
end
end
end
% sort counters in descending order (according to votes for each
% circle)
circles = flipud(sortrows(circles,4));
% get circle list's size
[rows cols] = size(circles);
% scan circle list and check each pair of found circles
for i = 1 : rows-1
% get first circle's details:
% center
cX1 = circles(i,1);
cY1 = circles(i,2);
% radius
r1 = circles(i,3);
%hough counter
h1 = circles(i,4);
for j = i+1 : rows
%get second circle's details:
% center
cX2 = circles(j,1);
cY2 = circles(j,2);
% radius
r2 = circles(j,3);
%hough counter
h2 = circles(j,4);
% check if circle's actual difference is smaller than minimal
% radius allowed
if (cX1 - cX2)*(cX1 - cX2)+ (cY1 - cY2)*(cY1 - cY2) < (min(r1,r2))*(min(r1,r2)) && abs(r1 - r2) < minR
% both circles are similar, sum their counters and merge
% them to a circle with their avaraged values
circles(i,:)=[(cX1+cX2)/2, (cY1+cY2)/2, (r1+r2)/2, h1+h2];
% remove similar circle
circles(j,:)=[0,0,0,0];
end
end
end
sortParam = 3; % 1: x-center, 2: y-center, 3: radius, 4: hough counter
% sort the circles by the sort parameter, in descending order
circles = flipud(sortrows(circles,sortParam));
% get number of remained circles (= rows with non-zero values)
len = length(find(circles~=0))/4;
% remove duplicate similar circles from previus step
circles(circles == 0) = [];
% reshape circle list back to matrix form (previous step converted it
% to a vector)
circles = reshape(circles,len,4);
% get max value according to sort parameter
m = max(circles(:,sortParam));
%get size of new circle list (with no duplicate circles)
[newH newW] = size(circles);
% thresholding: remove hough counters that are less than 30% from sort
% parameter
for i= 1 : newH
% check if current circle's sorting parameter's value is smaller
% than threshold
if m - circles(i,sortParam) < m * 0.3
% plot(circles(i,1),circles(i,2),'xr'); % DEBUG - show centers
else
% remove current circle
circles(i,:)=[0,0,0,0];
end
end
% find number of remaining circles after thresholding
len = length(find(circles~=0))/4;
% delete rows that match circles removed in thresholding
circles(circles==0)=[];
% reshape circle list back to matrix form
circles=reshape(circles,len,4);
% convert circle list's values to integers (hough counters are already
% integers)
circles = uint8(circles(:,1:3));
toc
end
このコードはどこで改善できますか?助けてくれてありがとう!