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;
}