绘制图像中某些点周围的边界 [英] Drawing a boundary around some dots in an image

查看:284
本文介绍了绘制图像中某些点周围的边界的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始使用opencv。我有一个图像有几个点在一行。我想在这些点周围做一个矩形边框。
我应用了一些基本的C算法,但它没有为我工作。
这是我的代码。

  int main()

{

cv :: Mat image = imread(C:/ Users / Ravi Sharma / Desktop / img.bmp);

for(int i = 0; i for(int k = 0; k if((image.at< cv :: Vec3b>(k,i)[0] == 0)&&(image.at< cv :: Vec3b>(k,i)[1] == 135)&&(image.at< cv :: Vec3b>(k,i)[2] == 255))
{
(image.at< cv :: Vec3b> ,i)[0] = 0)&(image.at< cv :: Vec3b>(k,i)[1] = 0)&(image.at< cv :: Vec3b> ,i)[2] = 255);
}
}

}
imwrite(C:/ Users / Ravi Sharma / Desktop / img1.bmp,image);
cv :: namedWindow(Window1);
cv :: imshow(Window1,image);
cv :: waitKey(50000);
return 1;
}

此代码不更新像素值。请帮助我纠正代码,以获得所需的结果。
我如何使用 cvminmaxloc 函数来做同样的事情。
Thanx。

解决方案

我将假设您的图片可以被视为二进制掩码,只感兴趣具有非零值的像素。





要在上面左侧图像中的点周围找到边框,请遍历图像中的所有像素。对于每个非零像素,检查其 xy 位置是否位于当前边界框之外。如果是,请更新您的边框。



下面是一个最低限度工作的例子,它生成一个包含随机抽样点的图像,其中边界

  //此示例使用OpenCV 3.0.0-beta。要使用OpenCV 2.4。* a 
//必须进行少量更改。

#include< opencv2 / core.hpp>
#include< opencv2 / highgui.hpp>
#include< opencv2 / imgproc.hpp>

cv :: Mat randomPoints(cv :: Size size = cv :: Size(320,240),int pointCount = 25)
{
cv :: RNG rng cv :: getCPUTickCount());
cv :: Mat image = cv :: Mat3b :: zeros(size);
int radius = 3;
cv ::标量颜色(0,153,255);
int thickness = -1;
int margin = std :: min(size.height,size.width)/ 4;

for(int i = 0; i< pointCount; ++ i)
{
cv :: Point p;
p.x = rng.uniform(margin,size.width - margin - 1);
p.y = rng.uniform(margin,size.height - margin - 1);
cv :: circle(image,p,radius,color,thickness);
}

return image;
}

int main(int argc,char ** argv)
{
#if 0
cv :: Mat image = imread :/ Users / Ravi Sharma / Desktop / img.bmp);
#else
cv:Mat image = randomPoints();
#endif

cv :: Mat imageGray;
cv :: cvtColor(image,imageGray,cv :: COLOR_BGR2GRAY);
cv :: Size size = imageGray.size();

//边界框由其左上(TL)和右下(BR)
//坐标定义。
cv :: Point tl(size.width,size.height);
cv :: Point br(0,0);
bool hasPoints = false;

for(int y = 0; y {
for(int x = 0; x< size.width; + + x)
{
if(imageGray.at< unsigned char>(y,x)> 0)
{
hasPoints = true;

//更新左上角。
if(x if(y
//更新右下角。
if(x> br.x)br.x = x;
if(y> br.y)br.y = y;
}
}
}

//如果图像包含任何非零像素,则绘制边界框。
if(hasPoints)
cv :: rectangle(image,tl,br,cv :: Scalar(255,255,255,255));

cv :: namedWindow(bounding-box);
cv :: imshow(bounding-box,image);
cv :: waitKey(0);

cv :: imwrite(bounding-box.png,image);
}

编辑1:
$ b

我也喜欢@Micka提出的想法,即使用 cv :: boundingRect()。所以,在上面的代码示例中的循环内,你将所有 xy - 非零像素的位置推入 std :: vector< cv :: Point> 然后调用 cv :: boundingRect 。在这种情况下,您还可以查看凸包的二维点云。


I have recently started working on opencv. I have an image having several dots in a line. I want to make a rectangular border around these dots. I have applied some basic C algorithm but it didn't work for me. This is my code.

int main()

{

    cv::Mat image = imread("C:/Users/Ravi Sharma/Desktop/img.bmp");

     for(int i =0; i < image.rows; i++){
        for(int k = 0; k <image.cols; k ++){
            if((image.at<cv::Vec3b>(k,i)[0] == 0)&&(image.at<cv::Vec3b>(k,i)[1] == 135)&&(image.at<cv::Vec3b>(k,i)[2] == 255))
            {
            (image.at<cv::Vec3b>(k,i)[0] = 0)&&(image.at<cv::Vec3b>(k,i)[1] = 0)&&(image.at<cv::Vec3b>(k,i)[2] = 255);
            }
        }

    }
    imwrite("C:/Users/Ravi Sharma/Desktop/img1.bmp",image);
    cv::namedWindow("Window1");
    cv::imshow("Window1",image);
    cv::waitKey(50000);
    return 1;
} 

This code is not updating the pixel value. Please help me correcting the code to get the desired result. How I can use cvminmaxloc function to do the same. Thanx in advance.

解决方案

I will assume that your image can be treated as a binary mask and that we are only interested in pixels with non-zero values.

To find the bounding box around the points in the left image above, iterate over all pixels in the image. For every non-zero pixel, check if its xy-location lies outside the current bounding box. If it does, then update your bounding box. The resulting bounding box will enclose all points, as in the right image above.

Below is a minimally working example, which generates an image containing randomly sampling points for which a bounding box is determined.

// This example uses OpenCV 3.0.0-beta. To use with OpenCV 2.4.* a
// few changes have to be made.

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

cv::Mat randomPoints( cv::Size size = cv::Size( 320, 240 ), int pointCount = 25 )
{
    cv::RNG rng( cv::getCPUTickCount() );
    cv::Mat image = cv::Mat3b::zeros( size );
    int radius = 3;
    cv::Scalar color( 0, 153, 255 );
    int thickness = -1;
    int margin = std::min( size.height, size.width ) / 4;

    for ( int i = 0; i < pointCount; ++i )
    {
        cv::Point p;
        p.x = rng.uniform( margin, size.width  - margin - 1 );
        p.y = rng.uniform( margin, size.height - margin - 1 );
        cv::circle( image, p, radius, color, thickness );
    }

    return image;
}

int main( int argc, char ** argv )
{
#if 0
    cv::Mat image = imread( "C:/Users/Ravi Sharma/Desktop/img.bmp" );
#else
    cv::Mat image = randomPoints();
#endif

    cv::Mat imageGray;
    cv::cvtColor( image, imageGray, cv::COLOR_BGR2GRAY );
    cv::Size size = imageGray.size();

    // The bounding box is defined by its top-left (TL) and bottom-right (BR)
    // coordinates.
    cv::Point tl( size.width, size.height );
    cv::Point br(          0,           0 );
    bool hasPoints = false;

    for ( int y = 0; y < size.height; ++y )
    {
        for ( int x = 0; x < size.width; ++x )
        {
            if ( imageGray.at<unsigned char>( y, x ) > 0 )
            {
                hasPoints = true;

                // Update the top-left corner.
                if ( x < tl.x ) tl.x = x;
                if ( y < tl.y ) tl.y = y;

                // Update the bottom-right corner.
                if ( x > br.x ) br.x = x;
                if ( y > br.y ) br.y = y;
            }
        }
    }

    // If the image contains any non-zero pixels, then draw the bounding box.
    if ( hasPoints )
        cv::rectangle( image, tl, br, cv::Scalar( 255, 255, 255, 255 ) );

    cv::namedWindow( "bounding-box" );
    cv::imshow( "bounding-box", image );
    cv::waitKey( 0 );

    cv::imwrite( "bounding-box.png", image );
}

EDIT 1:

I also like the idea suggested by @Micka above, i.e. using cv::boundingRect(). So, inside the loop in the above code example you would push all xy-locations of non-zeros pixels into a std::vector< cv::Point > and then call cv::boundingRect. In that context it is also interesting to look at the convex hull of a 2D point cloud.

这篇关于绘制图像中某些点周围的边界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆