Image processing 当我只看到外边缘时,如何找到圆心?
使用matlab,我需要通过编程找到圆心,而我只能看到圆的外缘 下面是我正在尝试处理的测试图像: 忽略外边缘周围的黑色。我把相机放在一个望远镜的后面,这就是为什么你只能在中间看到一个小的放大的圆。这些黑圈实际上是一个目标,因此有多个环相互嵌套。 使用imfindcircles()的脚本 在下面的matlab脚本中,我使用了imfindcircles()。imfindcircles()有两个问题。 1.每次调用大约需要2-3秒,这会降低我的应用程序的速度。 2.在上面的示例图像中,它无法预测圆心。它需要先看到更多的圆圈Image processing 当我只看到外边缘时,如何找到圆心?,image-processing,matlab,Image Processing,Matlab,使用matlab,我需要通过编程找到圆心,而我只能看到圆的外缘 下面是我正在尝试处理的测试图像: 忽略外边缘周围的黑色。我把相机放在一个望远镜的后面,这就是为什么你只能在中间看到一个小的放大的圆。这些黑圈实际上是一个目标,因此有多个环相互嵌套。 使用imfindcircles()的脚本 在下面的matlab脚本中,我使用了imfindcircles()。imfindcircles()有两个问题。 1.每次调用大约需要2-3秒,这会降低我的应用程序的速度。 2.在上面的示例图像中,它无法预测圆心
Rmin = 40; %7 and 12 for small circle
Rmax = 100;
% Create video input object.
vid = videoinput('winvideo',1);
% Set video input object properties for this application.
% Note that example uses both SET method and dot notation method.
set(vid,'TriggerRepeat',100);
vid.FrameGrabInterval = 5;
vid = videoinput('winvideo', 1, 'MJPG_1280x720');
%src = getselectedsource(vid);
%number of frames to get each time the camera is triggered
vid.FramesPerTrigger = 1;
%return grayscale for one less thing to process
vid.ReturnedColorspace = 'grayscale';
%make the trigger type manual. This allows use to grab one frame at a time
triggerconfig(vid, 'manual');
% allow us to capture unlimited frames, with only starting the video once
vid.TriggerRepeat = Inf;
%preview(vid);
%start(vid);
%trigger(vid);
%stoppreview(vid);
% Create a figure window.
%figure;
% Start acquiring frames.
start(vid);
while(true)
trigger(vid);
%get a single image frame
image = getdata(vid);
%draw the image on screen
imshow(image);
drawnow; % update figure window
%set the center of the image. This is used as an additional way to
%calibrate the score, camera, and laser. You can change where the "center" of
%the camera image is by adjusting these values.
% [x, y]
imageCenter = [500, 500];
viscircles(imageCenter, 5,'EdgeColor','r');
%find circles (the target) in the image and draw a circle around it
[centers, radii, metric] = imfindcircles(image,[Rmin Rmax], 'ObjectPolarity', 'dark');
%make sure a circle on screen was found
if(centers)
%draw circle found on screen
viscircles(centers, radii,'EdgeColor','b');
%calculate distance from center of the image and the center of the circle
%x minus x; y minus y; then calc hypotenuse
circleCenterX = centers(1,1);
circleCenterY = centers(1,2);
imageCenterX = imageCenter(1,1);
imageCenterY = imageCenter(1,2);
%calculate the di
distanceX = circleCenterX - imageCenterX;
distanceY = circleCenterY - imageCenterY ;
%calculate the hypotenuse (b^2 + b^2 = c^2)
hypotenuse = sqrt(distanceX^2 + distanceY^2);
%create sound based on distance from the center of the image
a=sin(2*pi*hypotenuse*(0:0.000125:0.05));
sound(a);
disp(hypotenuse);
%if you are withing X pixel of the center make a beeping noise
if(hypotenuse <= 15)
a=sin(2*pi*400*(0:0.000125:0.05));
sound(a);
sound(a);
sound(a);
end
%show a measuring line to verfiy results
%h = imdistline;
end
%clear memory after each frame to avoid memory leak
flushdata(vid, 'triggers');
end
%doesnät get run but use these commands to clean up before running the
%script again
imaqreset();
%stop(vid);
%delete(vid);
%clear;
%close(gcf);
Rmin=40;%7和12表示小圆
Rmax=100;
%创建视频输入对象。
vid=视频输入(“winvideo”,1);
%为此应用程序设置视频输入对象属性。
%请注意,该示例同时使用SET方法和点表示法。
设置(视频,'TriggerRepeat',100);
vid.FrameGrabInterval=5;
vid=视频输入(“winvideo”,1,“MJPG_1280x720”);
%src=getselectedsource(vid);
%每次触发相机时要获取的帧数
vid.FramesPerTrigger=1;
%返回要处理的少一件事情的灰度值
vid.ReturnedColorspace=‘灰度’;
%使触发器类型为手动。这允许用户一次抓取一帧
triggerconfig(见“手动”);
%允许我们捕获无限帧,只需启动一次视频
vid.triggerreat=Inf;
%预览(vid);
%启动(vid);
%触发器(vid);
%审查(vid);
%创建一个图形窗口。
%数字;
%开始获取帧。
启动(vid);
while(true)
触发器(vid);
%获取单个图像帧
图像=获取数据(vid);
%在屏幕上绘制图像
imshow(图像);
现在提取;%更新图形窗口
%设置图像的中心。这是用来作为一个额外的方式
%校准分数、摄像机和激光器。您可以更改“中心”的位置
%通过调整这些值,可以创建相机图像。
%[x,y]
图像中心=[500500];
viscircles(图像中心,5,'EdgeColor','r');
%在图像中找到圆(目标),并在其周围画一个圆
[中心,半径,公制]=imfindcircles(图像,[Rmin Rmax],'ObjectPolarity','dark');
%确保在屏幕上找到一个圆圈
国际单项体育联合会(中心)
%绘制屏幕上的圆圈
内圆(中心、半径、“边缘颜色”、“b”);
%计算从图像中心到圆心的距离
%x减去x;y减去y;然后计算斜边
CircleCenter=中心(1,1);
循环中心=中心(1,2);
imageCenterX=imageCenter(1,1);
imageCenterY=imageCenter(1,2);
%计算di
距离X=圆形中心X-图像中心X;
距离Y=循环中心-图像中心;
%计算斜边(b^2+b^2=c^2)
斜边=sqrt(距离X^2+距离Y^2);
%根据与图像中心的距离创建声音
a=sin(2*pi*斜边*(0:0.000125:0.05));
声音(a);
斜边;
%如果使用中心的X像素,则发出嘟嘟声
if(斜边100;%100
%图,imshow(BW);
%http://www.mathworks.de/de/help/images/ref/imdilate.html
%se=应力('线',11,90);
%I2=不扩张(体重,se);
%imshow(BW),标题(“原件”)
%图,imshow(I2),标题(“放大”)
原始体重=体重;
se=链状('圆盘',2);
DBW=imerode(原始BW,se);
%imshow(原始BW)、figure、imshow(原始BW)
%在二值图像中查找区域
区域图像=DBW;
s=区域属性(区域图像,图像,{'Centroid','WeightedCentroid','Area','FilledImage'});
%绘制屏幕上的区域。
如果(drawOnImage==1)
%图,imshow(区域图像);
标题(“加权(红色)和未加权(蓝色)质心位置”);
等等
numObj=numel(s);
对于k=1:numObj
%仅显示大于X像素数的区域
如果(s(k).Area>minPixelArea)
图(s(k).加权质心(1),s(k).加权质心(2),‘r*’;
图(s(k)。质心(1),s(k)。质心(2),‘bo’;
文本(s(k).形心(1),s(k).形心(2),sprintf(“%2.1f”,s(k).形心(1)),“EdgeColor”,“b”,“Color”,“r”);
结束
结束
拖延
结束
shortestDist=100;%存储找到的当前最短距离,默认为something massible,因此很容易被覆盖
shortestDistIndex=0;%存储具有最短距离的点的索引
对于idx=1:numel(s)
%确保当前元素的像素数大于X
%在处理之前
如果(s(idx).Area>minPixelArea)
%获取当前元素的x和y
电流x=s(idx)。质心(1);
电流y=s(idx)。质心(1);
%获取下一个元素的x和y
尝试
nextX=s(idx+1)。质心(1);
nextY=s(idx+1)。质心(1);
抓住
%如果我们在最后一个元素上,try语句将失败,并且
%这将结束for循环
打破
结束
%计算当前质心和下一个质心之间的距离
距离x=nextX-currentX;
距离y=nextY-当前y;
%计算斜边(b^2+b^2=c^2)
斜边=sqrt(距离X^2+距离Y^2);
%如果距离小于当前的“最短距离”,
%覆盖变量
如果(斜边您可以尝试Hough变换来检测圆。如果圆上有3个点(A、B、C),您可以计算它。外接圆的中心可以在任意两个垂线的交点处找到
function circleCenter = findCircleCenter(image, drawOnImage, toGray)
%in order to find the center, find the center of all objects in an image.
%Once we have the centers, we find the shortest distance between these
%objects. Our image has multiple circle, each inside the other. The center
%of all these cirlces are the same. By finding the shortest distance
%between the objects, we can safely assume we found the center of our
%target when we find two points are very close to each other.
%Adjust the number of pixels between the two points of the circle.
%Explained in details above.
minCenterPixelDist = 8;
%the minimum amount of pixels needed in a region to be considered an
%object for measurement
minPixelArea = 100;
if(toGray == 1)
%convert to grayscale
image = rgb2gray(image);
%figure, imshow(image);
end
%find the two closest points
%see if they are less than 8 pixels apart, this is the center
%threshold the image to make a binary image
BW = image > 100; %100
%figure, imshow(BW);
%http://www.mathworks.de/de/help/images/ref/imdilate.html
%se = strel('line',11,90);
%I2 = imdilate(BW,se);
%imshow(BW), title('Original')
%figure, imshow(I2), title('Dilated')
originalBW = BW;
se = strel('disk',2);
erodedBW = imerode(originalBW,se);
%imshow(originalBW), figure, imshow(erodedBW)
%find regions in binary image
regionImage = erodedBW;
s = regionprops(regionImage, image, {'Centroid','WeightedCentroid','Area','FilledImage'});
%draw the regions found on screen.
if(drawOnImage == 1)
%figure, imshow(regionImage);
title('Weighted (red) and Unweighted (blue) Centroid Locations');
hold on
numObj = numel(s);
for k = 1 : numObj
%only display regions that are bigger than X number of pixels
if(s(k).Area > minPixelArea)
plot(s(k).WeightedCentroid(1), s(k).WeightedCentroid(2), 'r*');
plot(s(k).Centroid(1), s(k).Centroid(2), 'bo');
text(s(k).Centroid(1),s(k).Centroid(2), sprintf('%2.1f', s(k).Centroid(1)), 'EdgeColor','b','Color','r');
end
end
hold off
end
shortestDist = 100; %stores the current shortest distance found, default to somethign massive so it gets overwriten easily
shortestDistIndex = 0;%stores the index of the point with the shortest distance
for idx = 1:numel(s)
%make sure the current element has more than X number of pixels
%before processing it
if(s(idx).Area > minPixelArea)
%get the x and y of the current element
currentX = s(idx).Centroid(1);
currentY = s(idx).Centroid(1);
%get the x and y of the next element
try
nextX = s(idx + 1).Centroid(1);
nextY = s(idx + 1).Centroid(1);
catch
%if we are on the last element, the try statement will fail, and
%this will end the for loop
break;
end
%calculate the distance between the current centroid and the next one
distanceX = nextX - currentX;
distanceY = nextY - currentY;
%calculate the hypotenuse (b^2 + b^2 = c^2)
hypotenuse = sqrt(distanceX^2 + distanceY^2);
%if the distance is less than the current "shortest distance",
%overwrite the variable
if(hypotenuse <= shortestDist)
shortestDist = hypotenuse;
shortestDistIndex = idx;
end
end
end
%if the closest points are within a certain number of pixels, we can
%assume the are the centers of two circles
%also make sure the area of this shortest distance is greater than
%minPixel area
if(shortestDist < minCenterPixelDist)
%get the x and y of our shortest distance centroids
centerOneX = s(shortestDistIndex).Centroid(1);
centerOneY = s(shortestDistIndex).Centroid(2);
centerTwoX = s(shortestDistIndex + 1).Centroid(1);
centerTwoY = s(shortestDistIndex + 1).Centroid(2);
%calculate the average between the two closest points
circleCenterX = (centerOneX + centerTwoX)/2;
circleCenterY = (centerOneY + centerTwoY)/2;
circleCenter = [circleCenterX, circleCenterY];
disp(circleCenter);
else
circleCenter = [];
end
end