1、引言
問題重述
已知書本上右下角放一枚一元人民幣(直徑2.5厘米),請利用計(jì)算機(jī)視覺技術(shù)預(yù)測圖片中目標(biāo)的實(shí)際尺寸。
1.預(yù)測圖片中書本的長與寬(單位:厘米)。
2.預(yù)測書本右上方用鉛筆畫的圓圈的外圓直徑(單位:厘米)。
現(xiàn)有解決方案:
手動(dòng)或自動(dòng)地對已知物體進(jìn)行標(biāo)注和測量,得到其尺寸信息(例如像素大小)。 對圖像進(jìn)行預(yù)處理,包括灰度化、二值化、去除噪聲等操作,以便更好地分割和識(shí)別圖像中的物體。 利用物體檢測或圖像分割技術(shù)找到圖像中待測物體的位置。 根據(jù)待測物體在圖像中的像素大小和已知物體的像素大小之間的比例關(guān)系,計(jì)算出待測物體的實(shí)際尺寸。
2、解決方法
先對圖片進(jìn)行預(yù)處理,后進(jìn)行高斯模糊(通過測試設(shè)置合理的閾值,從而得到較好的效果),通過閉運(yùn)算增加邊緣連通性,用來填充物體內(nèi)的小空洞,連接斷開的輪廓線,由于邊緣檢測出來的輪廓線通常是不完整的,我們就可以通過這種方法來加強(qiáng)邊緣,得到完整的邊緣。為了獲取到我們書本的輪廓,我們要提取最大的輪廓。然后提取通過霍夫變換檢測直線,求出書本輪廓的四條直線的角點(diǎn),也就是書本的四個(gè)角(求角點(diǎn)的時(shí)候要進(jìn)行篩選,篩選出符合要求的點(diǎn))。再通過角點(diǎn)以及透視變換對圖片進(jìn)行矯正,具體思路是先求出投影映射矩陣:根據(jù)4個(gè)基準(zhǔn)坐標(biāo),然后反求出源圖像坐標(biāo):根據(jù)映射矩陣內(nèi)參數(shù),求一個(gè)二元一次方程組。得到矯正后的圖片后我們同樣要進(jìn)行高斯模糊。之后我們對圖片使用圓形 Hough 變換查找圓,找出最符合的兩個(gè)圓,從而能求出書本的寬高和手畫的圓的直徑。
3.實(shí)驗(yàn)結(jié)果
書本邊緣(顯示角點(diǎn)):
透視變換后的圖片:
Hough 變換查找圓,并畫出來:
結(jié)果輸出:
4、結(jié)論
本次實(shí)驗(yàn)運(yùn)用了較多計(jì)算機(jī)視覺相關(guān)知識(shí),本人能通過課堂所學(xué)結(jié)合個(gè)人想法完成本次實(shí)驗(yàn)要求,較符合個(gè)人預(yù)期,能通過矯正圖片等創(chuàng)新方法使得結(jié)果更加準(zhǔn)確。但也存在一些不足,例如對手畫圓的檢測并不能十分精準(zhǔn),精度還有待提高。文章來源:http://www.zghlxwxcb.cn/news/detail-496457.html
5、參考文獻(xiàn)
[1]圖像透視變換原理及現(xiàn):https://blog.csdn.net/cuixing001/article/details/80261189
[2]透視變換的實(shí)現(xiàn)以及透視變換矩陣的構(gòu)造: https://blog.csdn.net/overflow_1/article/details/80330835
[3]opencv實(shí)戰(zhàn)–物體尺寸量:https://blog.csdn.net/mbtt00/article/details/107918654文章來源地址http://www.zghlxwxcb.cn/news/detail-496457.html
6、具體代碼如下:
% 讀入圖片并顯示
img = imread('image.jpg');
%imshow(img);
% 縮小圖片,方便處理
img = imresize(img, 0.5);
% 灰度化
grayImg = rgb2gray(img);
% 高斯模糊
blurImg = imgaussfilt(grayImg, 0.5); % 增加0.5個(gè)像素的模糊半徑
% Canny邊緣檢測
edgeImg = edge(blurImg, 'Canny', [0.05, 0.15]); % 設(shè)置閾值0.05和0.15
%imshow(edgeImg);
% 閉運(yùn)算,增加邊緣連通性
se = strel('disk', 200); % 200像素大小的圓形結(jié)構(gòu)元素
closedImg = imclose(edgeImg, se);
%imshow(closedImg);
% 提取輪廓
contourImg = bwperim(closedImg, 8); % 連續(xù)8個(gè)像素才能構(gòu)成邊緣
stats = regionprops(contourImg, 'BoundingBox', 'Area'); % 提取輪廓屬性
% 霍夫變換檢測直線
[H,T,R] = hough(contourImg);
P = houghpeaks(H, 50);
lines = houghlines(contourImg, T, R, P);
% 直線篩選
maxLength = 0;
longestLines = [];
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
% 計(jì)算直線長度
lineLength = norm(xy(1,:) - xy(2,:));
% 判斷是否為最長直線
if lineLength > maxLength
longestLines(end+1) = k;
if length(longestLines) > 4
[~, idx] = min(lineLength);
longestLines(idx) = [];
end
maxLength = lineLength;
end
end
% 計(jì)算直線交點(diǎn)
corners = zeros(4,2);
idx = 1;
for i = 1:length(longestLines)
for j = i+1:length(longestLines)
xy1 = [lines(longestLines(i)).point1; lines(longestLines(i)).point2];
xy2 = [lines(longestLines(j)).point1; lines(longestLines(j)).point2];
intPoint = lineIntersect(xy1, xy2);
if(intPoint(1)<640)
if(intPoint(2)>0)
corners(idx,:) = intPoint;
idx = idx + 1;
end
end
end
end
imshow(contourImg);title('書本邊緣(顯示角點(diǎn))');
hold on;
plot(corners(:,1), corners(:,2), 'ro', 'MarkerSize', 10); % 顯示角點(diǎn)
%plot(xy1(:,1),xy1(:,2),'LineWidth',1,'Color','red');
%plot(xy2(:,1),xy2(:,2),'LineWidth',1,'Color','green');
% 找到最大的輪廓,即書本的輪廓
[~, idx] = max([stats.Area]);
bookBox = stats(idx).BoundingBox;
disp(size(corners))
% 獲取書本輪廓的圖像并進(jìn)行矯正
%bookContour = imcrop(img, bookBox);
% 顯示矯正后的圖像
%figure;
%imshow(bookContour);
[m,n] = size(grayImg);
dot=corners; %取四個(gè)點(diǎn),依次是左上,右上,左下,右下
dot(:,[1,2])= dot(:,[2,1]); % 變換x y坐標(biāo),x=行 y=列
col=round(sqrt((dot(1,1)-dot(2,1))^2+(dot(1,2)-dot(2,2))^2)); %從原四邊形獲得新矩形寬
row=round(sqrt((dot(1,1)-dot(3,1))^2+(dot(1,2)-dot(3,2))^2)); %從原四邊形獲得新矩形高
new_img = ones(row,col);
% 原圖四個(gè)基準(zhǔn)點(diǎn)的坐標(biāo)
x = [dot(1,1),dot(2,1),dot(3,1),dot(4,1)];
y = [dot(1,2),dot(2,2),dot(3,2),dot(4,2)];
% 新圖四個(gè)基準(zhǔn)點(diǎn)坐標(biāo)
X = [1,1,row,row];
Y = [1,col,1,col];
% 列出投影關(guān)系 求出投影矩陣
A=[x(1),y(1),1,0,0,0,-X(1)*x(1),-X(1)*y(1);
0,0,0,x(1),y(1),1,-Y(1)*x(1),-Y(1)*y(1);
x(2),y(2),1,0,0,0,-X(2)*x(2),-X(2)*y(2);
0,0,0,x(2),y(2),1,-Y(2)*x(2),-Y(2)*y(2);
x(3),y(3),1,0,0,0,-X(3)*x(3),-X(3)*y(3);
0,0 ,0,x(3),y(3),1,-Y(3)*x(3),-Y(3)*y(3);
x(4),y(4),1,0,0,0,-X(4)*x(4),-X(4)*y(4);
0,0,0,x(4),y(4),1,-Y(4)*x(4),-Y(4)*y(4)];%求解變換矩陣的行列式
B = [X(1),Y(1),X(2),Y(2),X(3),Y(3),X(4),Y(4)]';
C = inv(A)*B;
D = [C(1),C(2),C(3);
C(4),C(5),C(6);
C(7),C(8),1]; % 變換矩陣3*3模式
inv_D = inv(D);
for i = 1:row
for j = 1:col
% 解二元一次方程組,根據(jù)目標(biāo)圖像坐標(biāo)反求出原圖坐標(biāo)
pix = inv_D * [i j 1]';
pix1 = inv([C(7)*pix(1)-1 C(8)*pix(1);C(7)*pix(2) C(8)*pix(2)-1])*[-pix(1) -pix(2)]';
if pix1(1)<m && pix1(2)<n
new_img(i,j) = img(round(pix1(1)),round(pix1(2))); %最近鄰插值
else
new_img(i,j) = 255;
end
end
end
figure;
new_img=flipud(new_img);%上下翻轉(zhuǎn)
%圖像歸一化
Bmax=max(max(new_img));
Bmin=min(min(new_img));
new_img=(new_img-Bmin)/(Bmax-Bmin);
imshow(new_img);title('透視變換后')
new_img = imgaussfilt(new_img, 2);
new_img=edge(new_img, 'Canny', [0.05, 0.15]); % 設(shè)置閾值0.05和0.15
figure;
imshow(new_img);title('邊緣檢測')
[centers,radii,metric] = imfindcircles(new_img,[20,500])
centersStrong2 = centers(1:2,:);
radiiStrong2 = radii(1:2);
metricStrong2 = metric(1:2);
viscircles(centersStrong5, radiiStrong5,'EdgeColor','b');
%長為A,寬為B
[A,B]=size(new_img);
A=(A/radiiStrong2(1,1)*0.5)*2.5;
B=(B/radiiStrong2(1,1)*0.5)*2.5;
%外圓直徑
W=(radiiStrong2(2,1)/radiiStrong2(1,1))*2.5;
disp('書本寬為:'+string(B)+'cm'+',書本長為:'+string(A)+'cm');
disp('鉛筆所畫的圓的外圓直徑為:'+string(W)+'cm');
function intPoint = lineIntersect(line1, line2)
% 計(jì)算兩條直線的交點(diǎn)
% line1: 直線1的兩個(gè)端點(diǎn)坐標(biāo),[x1,y1; x2,y2]
% line2: 直線2的兩個(gè)端點(diǎn)坐標(biāo),[x3,y3; x4,y4]
% 計(jì)算直線參數(shù)
A1 = line1(1,2) - line1(2,2);
B1 = line1(2,1) - line1(1,1);
C1 = line1(1,1)*line1(2,2) - line1(2,1)*line1(1,2);
A2 = line2(1,2) - line2(2,2);
B2 = line2(2,1) - line2(1,1);
C2 = line2(1,1)*line2(2,2) - line2(2,1)*line2(1,2);
% 計(jì)算交點(diǎn)
D = A1*B2 - A2*B1;
if D ~= 0
x = (B1*C2 - B2*C1) / D;
y = (A2*C1 - A1*C2) / D;
intPoint = [x, y];
else
intPoint = [nan, nan];
end
end
到了這里,關(guān)于基于opencv測量圖片中物體的尺寸(matlab實(shí)現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!