Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I've found the solution, the idea is to apply a filter by using a mask and then remove the pixels already accounted. Below the complete program. I have tested the code it works fine for objects having a straight line forms but for others forms like as circular I had inaccurate results.

 #include <iostream>
 #include <iomanip>
 #include <opencv2/opencv.hpp>
 #include "opencv2/imgproc/imgproc.hpp"

 using namespace std;
 using namespace cv;

 int main(int, char** argv){
    // Load source image
    Mat imgSource = imread(argv[1]);
    // Check if image is loaded fine
    if(!imgSource.data)
        cerr << "Add file name image !" << endl;
    // Show source image
    imshow("imgSource", imgSource);
    //Transform source image to gray if it is not
    Mat gray;
    if (imgSource.channels() == 3)
    {
        cvtColor(imgSource, gray, CV_BGR2GRAY);
    }
    else
    {
        gray = imgSource;
    }
    Mat imgBin, imgBiFilter;
    //threshold(gray, imgBin,0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
    threshold(gray, imgBin, 100, 255, 1);   
    // count all pixels of binary image
    for (int row = 0; row < imgBin.rows; row++)
    {
        for (int col = 0; col < imgBin.cols ; col++)
        {
            int pixelValue = imgBin.at<uchar>(row,col);
        }
    }
    //Total number of pixels
    int imgResol;
    imgResol = (imgBin.rows * imgBin.cols);
    vector<Point> pixel_contour;   // output, locations of non-zero pixels
    cv::findNonZero(imgBin, pixel_contour);
    //imshow("binary", imgBin);

    vector<Vec4i> hierarchy;
    vector<vector<Point> > contours;
    // extract only the external contour
    findContours(imgBin.clone(), contours, hierarchy, CV_RETR_EXTERNAL,
                 CV_CHAIN_APPROX_NONE);
   // draw the contours as a solid and create a mask of the object
    Mat mask = Mat::zeros(imgBin.size(), CV_8UC1);
    const int arrSize = contours.size();
    double arrArea[arrSize] ;
      for(size_t i = 0; i < contours.size(); i++)    {
       drawContours(mask, contours, i, Scalar(255, 255, 255),
                     CV_FILLED, 8, hierarchy, 0, Point());
    //imshow("mask", mask);
    vector<Point> all_pixels;   // output, locations of non-zero pixels
    cv::findNonZero(mask, all_pixels);
    //count pixel of objects
    int pixelR = pixel_contour.size() - all_pixels.size() ;
    double area = contourArea(contours[i]);

            //Select the range of areas to be considered
            if(area < 5 || 1e4 < area) continue;
            //cout << " pixelR: " << pixelR<< endl;
            drawContours(imgSource, contours, static_cast<int>(i), Scalar(0, 0, 255), 1,
                         8, hierarchy, 0);
            arrArea[i] = pixelR;
    }

    cout << "Ncont" << setw(7) << "Area" << endl;
    for(int j=0; j <contours.size(); j++)
    {
      if (j <=0 )
        {
          cout << j << setw(9) << fabs(arrArea[j] - pixel_contour.size()) << endl;
        }
        else
        {
            cout << j << setw(9) << fabs(arrArea[j] - arrArea[j-1]) <<endl;
        }
    }


    //waitKey(0);
    return 0;
}

I've found the solution, the idea is to apply a filter by using a mask and then remove the pixels already accounted. Below the complete program. I have tested the code it works fine for objects having a straight line forms but for others forms like as circular I had inaccurate results. see my comment

 #include <iostream>
 #include <iomanip>
 #include <opencv2/opencv.hpp>
 #include "opencv2/imgproc/imgproc.hpp"

 using namespace std;
 using namespace cv;

 int main(int, char** argv){
    // Load source image
    Mat imgSource = imread(argv[1]);
    // Check if image is loaded fine
    if(!imgSource.data)
        cerr << "Add file name image !" << endl;
    // Show source image
    imshow("imgSource", imgSource);
    //Transform source image to gray if it is not
    Mat gray;
    if (imgSource.channels() == 3)
    {
        cvtColor(imgSource, gray, CV_BGR2GRAY);
    }
    else
    {
        gray = imgSource;
    }
    Mat imgBin, imgBiFilter;
    //threshold(gray, imgBin,0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
    threshold(gray, imgBin, 100, 255, 1);   
    // count all pixels of binary image
    for (int row = 0; row < imgBin.rows; row++)
    {
        for (int col = 0; col < imgBin.cols ; col++)
        {
            int pixelValue = imgBin.at<uchar>(row,col);
        }
    }
    //Total number of pixels
    int imgResol;
    imgResol = (imgBin.rows * imgBin.cols);
    vector<Point> pixel_contour;   // output, locations of non-zero pixels
    cv::findNonZero(imgBin, pixel_contour);
    //imshow("binary", imgBin);

    vector<Vec4i> hierarchy;
    vector<vector<Point> > contours;
    // extract only the external contour
    findContours(imgBin.clone(), contours, hierarchy, CV_RETR_EXTERNAL,
                 CV_CHAIN_APPROX_NONE);
   // draw the contours as a solid and create a mask of the object
    Mat mask = Mat::zeros(imgBin.size(), CV_8UC1);
    const int arrSize = contours.size();
    double arrArea[arrSize] ;
      for(size_t i = 0; i < contours.size(); i++)    {
       drawContours(mask, contours, i, Scalar(255, 255, 255),
                     CV_FILLED, 8, hierarchy, 0, Point());
    //imshow("mask", mask);
    vector<Point> all_pixels;   // output, locations of non-zero pixels
    cv::findNonZero(mask, all_pixels);
    //count pixel of objects
    int pixelR = pixel_contour.size() - all_pixels.size() ;
    double area = contourArea(contours[i]);

            //Select the range of areas to be considered
            if(area < 5 || 1e4 < area) continue;
            //cout << " pixelR: " << pixelR<< endl;
            drawContours(imgSource, contours, static_cast<int>(i), Scalar(0, 0, 255), 1,
                         8, hierarchy, 0);
            arrArea[i] = pixelR;
    }

    cout << "Ncont" << setw(7) << "Area" << endl;
    for(int j=0; j <contours.size(); j++)
    {
      if (j <=0 )
        {
          cout << j << setw(9) << fabs(arrArea[j] - pixel_contour.size()) << endl;
        }
        else
        {
            cout << j << setw(9) << fabs(arrArea[j] - arrArea[j-1]) <<endl;
        }
    }


    //waitKey(0);
    return 0;
}

see my commentI've found the solution, the idea is to apply a filter by using a mask and then remove the pixels already accounted. Below the complete program. I have tested the code it works fine for objects having a straight line forms but for others forms like as circular I had inaccurate results.

 #include <iostream>
 #include <iomanip>
 #include <opencv2/opencv.hpp>
 #include "opencv2/imgproc/imgproc.hpp"

 using namespace std;
 using namespace cv;

 int main(int, char** argv){
    // Load source image
    Mat imgSource = imread(argv[1]);
    // Check if image is loaded fine
    if(!imgSource.data)
        cerr << "Add file name image !" << endl;
    // Show source image
    imshow("imgSource", imgSource);
    //Transform source image to gray if it is not
    Mat gray;
    if (imgSource.channels() == 3)
    {
        cvtColor(imgSource, gray, CV_BGR2GRAY);
    }
    else
    {
        gray = imgSource;
    }
    Mat imgBin, imgBiFilter;
    //threshold(gray, imgBin,0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
    threshold(gray, imgBin, 100, 255, 1);   
    // count all pixels of binary image
    for (int row = 0; row < imgBin.rows; row++)
    {
        for (int col = 0; col < imgBin.cols ; col++)
        {
            int pixelValue = imgBin.at<uchar>(row,col);
        }
    }
    //Total number of pixels
    int imgResol;
    imgResol = (imgBin.rows * imgBin.cols);
    vector<Point> pixel_contour;   // output, locations of non-zero pixels
    cv::findNonZero(imgBin, pixel_contour);
    //imshow("binary", imgBin);

    vector<Vec4i> hierarchy;
    vector<vector<Point> > contours;
    // extract only the external contour
    findContours(imgBin.clone(), contours, hierarchy, CV_RETR_EXTERNAL,
                 CV_CHAIN_APPROX_NONE);
   // draw the contours as a solid and create a mask of the object
    Mat mask = Mat::zeros(imgBin.size(), CV_8UC1);
    const int arrSize = contours.size();
    double arrArea[arrSize] ;
      for(size_t i = 0; i < contours.size(); i++)    {
       drawContours(mask, contours, i, Scalar(255, 255, 255),
                     CV_FILLED, 8, hierarchy, 0, Point());
    //imshow("mask", mask);
    vector<Point> all_pixels;   // output, locations of non-zero pixels
    cv::findNonZero(mask, all_pixels);
    //count pixel of objects
    int pixelR = pixel_contour.size() - all_pixels.size() ;
    double area = contourArea(contours[i]);

            //Select the range of areas to be considered
            if(area < 5 || 1e4 < area) continue;
            //cout << " pixelR: " << pixelR<< endl;
            drawContours(imgSource, contours, static_cast<int>(i), Scalar(0, 0, 255), 1,
                         8, hierarchy, 0);
            arrArea[i] = pixelR;
    }

    cout << "Ncont" << setw(7) << "Area" << endl;
    for(int j=0; j <contours.size(); j++)
    {
      if (j <=0 )
        {
          cout << j << setw(9) << fabs(arrArea[j] - pixel_contour.size()) << endl;
        }
        else
        {
            cout << j << setw(9) << fabs(arrArea[j] - arrArea[j-1]) <<endl;
        }
    }


    //waitKey(0);
    return 0;
}

I've found rewritten the solution, code, the idea is to apply a filter by using a mask and then remove the pixels already accounted. Below the complete program. I have tested the code it works fine for objects having a straight line forms but for others forms like as circular I had inaccurate results.

 #include <iostream>
 #include <iomanip>
 #include <opencv2/opencv.hpp>
 #include "opencv2/imgproc/imgproc.hpp"

 using namespace std;
 using namespace cv;

 int main(int, char** argv){
    // Load source image
    Mat imgSource = imread(argv[1]);
    // Check if image is loaded fine
    if(!imgSource.data)
        cerr << "Add file name image !" << endl;
    // Show source image
    imshow("imgSource", imgSource);
    //Transform source image to gray if it is not
    Mat gray;
    if (imgSource.channels() == 3)
    {
        cvtColor(imgSource, gray, CV_BGR2GRAY);
    }
    else
    {
        gray = imgSource;
    }
    Mat imgBin, imgBiFilter;
    //threshold(gray, imgBin,0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
    threshold(gray, imgBin, 100, 255, 1);   
    // count all pixels of binary image
    for (int row = 0; row < imgBin.rows; row++)
    {
        for (int col = 0; col < imgBin.cols ; col++)
        {
            int pixelValue = imgBin.at<uchar>(row,col);
        }
    }
    //Total number of pixels
    int imgResol;
    imgResol = (imgBin.rows * imgBin.cols);
    vector<Point> pixel_contour;   // output, locations of non-zero pixels
    cv::findNonZero(imgBin, pixel_contour);
    //imshow("binary", imgBin);

    vector<Vec4i> hierarchy;
    vector<vector<Point> > contours;
    // extract only the external contour
    findContours(imgBin.clone(), contours, hierarchy, CV_RETR_EXTERNAL,
                 CV_CHAIN_APPROX_NONE);
   // draw the contours as a solid and create a mask of the object
    Mat mask = Mat::zeros(imgBin.size(), CV_8UC1);
    const int arrSize = contours.size();
    double arrArea[arrSize] ;
      for(size_t i = 0; i < contours.size(); i++)    {
       drawContours(mask, contours, i, Scalar(255, 255, 255),
                     CV_FILLED, 8, hierarchy, 0, Point());
    //imshow("mask", mask);
    vector<Point> all_pixels;   // output, locations of non-zero pixels
    cv::findNonZero(mask, all_pixels);
    //count pixel of objects
    int pixelR = pixel_contour.size() - all_pixels.size() ;
    double area = contourArea(contours[i]);

            //Select the range of areas to be considered
            if(area < 5 || 1e4 < area) continue;
            //cout << " pixelR: " << pixelR<< endl;
            drawContours(imgSource, contours, static_cast<int>(i), Scalar(0, 0, 255), 1,
                         8, hierarchy, 0);
            arrArea[i] = pixelR;
    }

    cout << "Ncont" << setw(7) << "Area" << endl;
    for(int j=0; j <contours.size(); j++)
    {
      if (j <=0 )
        {
          cout << j << setw(9) << fabs(arrArea[j] - pixel_contour.size()) << endl;
        }
        else
        {
            cout << j << setw(9) << fabs(arrArea[j] - arrArea[j-1]) <<endl;
        }
    }


    //waitKey(0);
    return 0;
}

I've rewritten the code, the idea is to apply a filter by using a mask and then remove the pixels already accounted. Below the complete program. I have tested the code it works fine for objects having a straight line forms but for others forms like as circular I had some inaccurate results.

 #include <iostream>
 #include <iomanip>
 #include <opencv2/opencv.hpp>
 #include "opencv2/imgproc/imgproc.hpp"

 using namespace std;
 using namespace cv;

 int main(int, char** argv){
    // Load source image
    Mat imgSource = imread(argv[1]);
    // Check if image is loaded fine
    if(!imgSource.data)
        cerr << "Add file name image !" << endl;
    // Show source image
    imshow("imgSource", imgSource);
    //Transform source image to gray if it is not
    Mat gray;
    if (imgSource.channels() == 3)
    {
        cvtColor(imgSource, gray, CV_BGR2GRAY);
    }
    else
    {
        gray = imgSource;
    }
    Mat imgBin, imgBiFilter;
    //threshold(gray, imgBin,0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
    threshold(gray, imgBin, 100, 255, 1);   
    // count all pixels of binary image
    for (int row = 0; row < imgBin.rows; row++)
    {
        for (int col = 0; col < imgBin.cols ; col++)
        {
            int pixelValue = imgBin.at<uchar>(row,col);
        }
    }
    //Total number of pixels
    int imgResol;
    imgResol = (imgBin.rows * imgBin.cols);
    vector<Point> pixel_contour;   // output, locations of non-zero pixels
    cv::findNonZero(imgBin, pixel_contour);
    //imshow("binary", imgBin);

    vector<Vec4i> hierarchy;
    vector<vector<Point> > contours;
    // extract only the external contour
    findContours(imgBin.clone(), contours, hierarchy, CV_RETR_EXTERNAL,
                 CV_CHAIN_APPROX_NONE);
   // draw the contours as a solid and create a mask of the object
    Mat mask = Mat::zeros(imgBin.size(), CV_8UC1);
    const int arrSize = contours.size();
    double arrArea[arrSize] ;
      for(size_t i = 0; i < contours.size(); i++)    {
       drawContours(mask, contours, i, Scalar(255, 255, 255),
                     CV_FILLED, 8, hierarchy, 0, Point());
    //imshow("mask", mask);
    vector<Point> all_pixels;   // output, locations of non-zero pixels
    cv::findNonZero(mask, all_pixels);
    //count pixel of objects
    int pixelR = pixel_contour.size() - all_pixels.size() ;
    double area = contourArea(contours[i]);

            //Select the range of areas to be considered
            if(area < 5 || 1e4 < area) continue;
            //cout << " pixelR: " << pixelR<< endl;
            drawContours(imgSource, contours, static_cast<int>(i), Scalar(0, 0, 255), 1,
                         8, hierarchy, 0);
            arrArea[i] = pixelR;
    }

    cout << "Ncont" << setw(7) << "Area" << endl;
    for(int j=0; j <contours.size(); j++)
    {
      if (j <=0 )
        {
          cout << j << setw(9) << fabs(arrArea[j] - pixel_contour.size()) << endl;
        }
        else
        {
            cout << j << setw(9) << fabs(arrArea[j] - arrArea[j-1]) <<endl;
        }
    }


    //waitKey(0);
    return 0;
}