简体   繁体   English

如何计算二进制图像上的白色物体?

[英]How to count white object on Binary Image?

I'm trying to count object from image. 我正试图从图像中计算对象。 I use logs photo, and I use some steps to get a binary image. 我使用日志照片,并使用一些步骤来获取二进制图像。 在此输入图像描述

This is my code: 这是我的代码:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <features2d.hpp>
using namespace cv;
using namespace std;
int main(int argc, char *argv[])
{
    //load image
    Mat img = imread("kayu.jpg", CV_LOAD_IMAGE_COLOR);
    if(img.empty())
       return -1;
    //namedWindow( "kayu", CV_WINDOW_AUTOSIZE );
    imshow("kayu", img);

    //convert to b/w
    Mat bw;
    cvtColor(img, bw, CV_BGR2GRAY);
    imshow("bw1", bw);

    threshold(bw, bw, 40, 255, CV_THRESH_BINARY);
    imshow("bw", bw);

    //distance transform & normalisasi
    Mat dist;
    distanceTransform(bw, dist, CV_DIST_L2, 3);
    normalize(dist, dist, 0, 2., NORM_MINMAX);
    imshow("dist", dist);

    //threshold to draw line
    threshold(dist, dist, .5, 1., CV_THRESH_BINARY);
    imshow("dist2", dist);

    //dist = bw;
    //dilasi
    Mat dilation, erotion, element;
    int dilation_type = MORPH_ELLIPSE;
    int dilation_size = 17;

    element = getStructuringElement(dilation_type, Size(2*dilation_size + 1, 2*dilation_size+1), Point(dilation_size, dilation_size ));
    erode(dist, erotion, element);
    int erotionCount = 0;
    for(int i=0; i<erotionCount; i++){
        erode(erotion, erotion, element);
    }
    imshow("erotion", erotion);

    dilate(erotion, dilation, element);
    imshow("dilation", dilation);
    waitKey(0);
    return 0;
}

As you can see, I use Erosion and Dilation to get better circular object of log. 如您所见,我使用侵蚀和膨胀来获得更好的圆形对象。 My problem is, I'm stuck at counting the object. 我的问题是,我坚持计算对象。 I tried SimpleBlobDetector but I got nothing, because when I try to convert the result of "dilation" step to CV_8U , the white object disappear. 我尝试了SimpleBlobDetector但我没有得到任何东西,因为当我尝试将“dilation”步骤的结果转换为CV_8U ,白色对象消失了。 I got error too when I use findContours() . 我使用findContours()时也遇到了错误。 It say something about channel of image. 它讲述了关于图像通道的一些信息。 I can't show the error here, because that's too many step and I already delete it from my code. 我无法在这里显示错误,因为这个步骤太多了,我已经从代码中删除了它。

Btw, at the end, i got 1 channel of image. 顺便说一句,最后,我得到了一个图像通道。 在此输入图像描述 Can i just use it to counting, or am i have to convert it and what is the best method to do it? 我可以用它来计算,或者我必须转换它,最好的方法是什么?

Two simple steps: 两个简单的步骤:

  1. Find contours for the binarized image. 查找二值化图像的轮廓。
  2. Get the count of the contours. 获取轮廓的数量。

Code: 码:

int count_trees(const cv::Mat& bin_image){
    cv::Mat img;
    if(bin_image.channels()>1){
        cv::cvtColor(bin_image,img,cv::COLOR_BGR2GRAY);
    }
    else{
         img=bin_image.clone();;
    }
    if(img.type()!=CV_8UC1){
        img*=255.f; //This could be stupid, but I do not have an environment to try it
        img.convertTo(img,CV_8UC1);
    }

    std::vector<std::vector<cv::Point>> contours
    std::vector<Vec4i> hierarchy;
    cv::findContours( img, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    return contours.size();
}

I have the same problem, here's an idea I'm about to implement. 我有同样的问题,这是我即将实施的想法。

1) Represent your image as an array of integers; 1)将图像表示为整数数组; 0 = black, 1 = white . 0 = black, 1 = white

2) set N = 2 ; 2)设置N = 2 ;

3) Scan your image, pixel-by-pixel. 3)逐个像素地扫描图像。 Whenever you find a white pixel, activate a flood-fill algorithm, starting at the pixel just found; 每当你找到一个白色像素时,激活一个泛光填充算法,从刚找到的像素开始; paint the region with the value of N++ ; N++的值绘制区域;

4) Iterate 3 until you reach the last pixel. 4)迭代3直到你到达最后一个像素。 ( N-2 ) is the number of regions found. N-2 )是找到的区域数量。

This method depends on the shape of the objects; 这种方法取决于物体的形状; mine are more chaotic than yours (wish me luck..). 我的比你的更混乱(祝我好运..)。 I'll make use of a recursive flood-fill recipe found somewhere (maybe Rosetta Code). 我将使用在某处找到的递归洪水填充配方(可能是Rosetta Code)。

This solution also makes it easy to compute the size of each region. 此解决方案还可以轻松计算每个区域的大小。

try to apply that on the your deleted img 尝试将其应用于您删除的img

// count
for (int i = 0; i< contours.size(); i = hierarchy[i][0]) // iteration sur chaque contour .
{
    Rect r = boundingRect(contours[i]);
    if (hierarchy[i][2]<0) {
        rectangle(canny_output, Point(r.x, r.y), Point(r.x + r.width, r.y + r.height), Scalar(20, 50, 255), 3, 8, 0);
        count++;
    }
}
cout << "Numeber of contour = " << count << endl;
imshow("src", src);
imshow("contour", dst);
waitKey(0);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM