如何在图像/视频中找到对象,了解其真实的物理尺寸?

时间:2016-07-29 09:14:47

标签: c++ matlab image-processing

我有一个图像样本,并希望在图像/视频中检测到对象已经预先知道该对象的真实物理尺寸。我有一个图像样本(它的飞机门),并希望找到飞机门上的窗户知道它的物理尺寸(让我们说它的内半径为20厘米,半径为23厘米)和它在真实世界中的位置。门(例如它到门框的最小距离是15厘米)。我也可以事先知道我的相机分辨率。任何可以通过图像处理自动完成的matlab代码或OpenCV C ++? 这是我的图片样本 door sample

带有圆形徽标的更复杂图像。 complex image

我运行第二个复杂图像的代码,但得不到相同的结果。这是图像结果。 Results of complex image

2 个答案:

答案 0 :(得分:1)

您正在寻找图像中的圆圈,因此我建议您使用霍夫圆变换。

  1. 将图片转换为灰色
  2. 在图像中查找边缘
  3. 使用Hugh圆形变换在图像中查找圆圈。
  4. 对于每个候选圆样本,圆的值以及值是否对应于预定义的值。
  5. 代码:

    clear all
    
    % Parameters
    minValueWindow = 90;
    maxValueWindow = 110;
    
    % Read file
    I = imread('image1.jpg');
    Igray = rgb2gray(I);
    [row,col] = size(Igray);
    
    % Edge detection
    Iedge = edge(Igray,'canny',[0 0.3]);
    
    % Hough circle transform
    rad = 40:80; % The approximate radius in pixels
    detectedCircle = {};
    detectedCircleIndex = 1;
    for radIndex=1:1:length(rad)
        [y0detect,x0detect,Accumulator] = houghcircle(Iedge,rad(1,radIndex),rad(1,radIndex)*pi/2);
    
        if ~isempty(y0detect)
            circles = struct;
            circles.X = x0detect;
            circles.Y = y0detect;
            circles.Rad = rad(1,radIndex);
            detectedCircle{detectedCircleIndex} = circles;
            detectedCircleIndex = detectedCircleIndex + 1;
        end
    end
    
    % For each detection run a color filter
    ang=0:0.01:2*pi; 
    finalCircles = {};
    finalCircleIndex = 1;
    
    for i=1:1:detectedCircleIndex-1
    
        rad = detectedCircle{i}.Rad;
        xp = rad*cos(ang);
        yp = rad*sin(ang);
    
        for detectedPointIndex=1:1:length(detectedCircle{i}.X)
    
            % Take each detected center and sample the gray image
            samplePointsX = round(detectedCircle{i}.X(detectedPointIndex) + xp);
            samplePointsY = round(detectedCircle{i}.Y(detectedPointIndex) + yp);
    
            sampleValueInd = sub2ind([row,col],samplePointsY,samplePointsX);
            sampleValueMean = mean(Igray(sampleValueInd));
    
            % Check if the circle color is good
            if(sampleValueMean > minValueWindow && sampleValueMean < maxValueWindow)
                circle = struct();
                circle.X = detectedCircle{i}.X(detectedPointIndex);
                circle.Y = detectedCircle{i}.Y(detectedPointIndex);
                circle.Rad = rad;
                finalCircles{finalCircleIndex} = circle;
                finalCircleIndex = finalCircleIndex + 1;
            end
        end
    end
    
    % Find Main circle by merging close hyptosis together
    for finaCircleInd=1:1:length(finalCircles)
        circleCenter(finaCircleInd,1) = finalCircles{finaCircleInd}.X;
        circleCenter(finaCircleInd,2) = finalCircles{finaCircleInd}.Y;
        circleCenter(finaCircleInd,3) = finalCircles{finaCircleInd}.Rad;
    end
    [ind,C] = kmeans(circleCenter,2);
    c = [length(find(ind==1));length(find(ind==2))];
    [~,maxInd] = max(c);
    xCircle = median(circleCenter(ind==maxInd,1));
    yCircle = median(circleCenter(ind==maxInd,2));
    radCircle = median(circleCenter(ind==maxInd,3));
    % Plot circle
    imshow(Igray);
    hold on
    
    ang=0:0.01:2*pi;
    xp=radCircle*cos(ang);
    yp=radCircle*sin(ang);
    plot(xCircle+xp,yCircle+yp,'Color','red', 'LineWidth',5);
    

    结果图片: enter image description here

    说明:

    • 对于其他图像,仍然需要微调几个参数,例如搜索颜色的半径和Ho​​ugh圆阈值以及精确边缘阈值。
    • 在我搜索半径为40到80的圆的函数中。在这里,您可以使用有关窗口的真实半径和摄像机分辨率的先前信息。如果你大致知道摄像机离飞机的距离和摄像机的分辨率以及窗口半径(cm),你可以使用它来获得半径(以像素为单位)并将其用于霍夫圆变换。

    enter image description here

答案 1 :(得分:-2)

我不会过分担心精确的几何和校准,而是根据自己的特点找到窗口。

二值化效果相对较好,无论是整个图像还是感兴趣的大区域。

然后,您可以根据它的近似面积和/或圆形度选择最可能的斑点。

enter image description here

enter image description here