UnaNancyOwen
11/25/2016 - 4:12 PM

main.cpp

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
//#include <ppl.h>
//#include <concurrent_vector.h>
#include <opencv2/opencv.hpp>

// opencv/samples/gpu/tick_meter.hpp
#include "tick_meter.hpp"

int main( int argc, char* argv[] )
{
    // Read Image
    cv::Mat image = cv::imread( "../image.bmp", cv::IMREAD_UNCHANGED );
    if( image.empty() ){
        return -1;
    }

    TickMeter tm;
    tm.start();

    // Resize
    const double scale = 0.5;
    cv::Mat resize;
    cv::resize( image, resize, cv::Size(), scale, scale, cv::INTER_NEAREST );

    // Convert HSV
    cv::Mat hsv;
    cv::cvtColor( resize, hsv, cv::COLOR_BGR2HSV, 3 );

    // Threshold
    cv::Scalar min( 40, 70, 70 ); // cv::Scalar( minH, minS, minV )
    cv::Scalar max( 80, 255, 255 ); // cv::Scalar( maxH, maxS, maxV )
    cv::Mat bin;
    cv::inRange( hsv, min, max, bin );

    // Labeling
    cv::Mat labels;
    cv::Mat stats;
    cv::Mat centroids;
    const int count = cv::connectedComponentsWithStats( bin, labels, stats, centroids );

    // Retrieve Max Area Label ( label 0 is background )
    // If number of labels is large, Please parallelize processing.
    std::vector<std::pair<int, int>> areas; // ( area, label )
    for( int i = 1; i < count; i++ ){
        areas.push_back( std::make_pair( stats.at<int>( i, cv::ConnectedComponentsTypes::CC_STAT_AREA ), i ) );
    }
    std::sort( areas.begin(), areas.end(), std::greater<std::pair<int, int>>() );
    /*
    concurrency::concurrent_vector<std::pair<int, int>> areas; // ( area, label )
    concurrency::parallel_for( 1, count, [&]( int i ){
        areas.push_back( std::make_pair( stats.at<int>( i, cv::ConnectedComponentsTypes::CC_STAT_AREA ), i ) );
    } );
    concurrency::parallel_sort( areas.begin(), areas.end(), std::greater<std::pair<int, int>>() );
    */
    const int maxarea = areas.cbegin()->second;

    // Retrieve Max Area Centroid ( sub-pixel accurate )
    const double rescale = 1.0 / scale;
    cv::Point2d centroid;
    centroid.x = centroids.at<double>( maxarea, 0 ) * rescale;
    centroid.y = centroids.at<double>( maxarea, 1 ) * rescale;
    std::cout << "Max Area Centroid : " << centroid << std::endl;

    tm.stop();
    std::cout << tm.getTimeMilli() << "[ms]" << std::endl;

    // Draw Centroid
    cv::circle( image, centroid, 3, cv::Scalar( 255, 255, 255 ), -1, cv::LINE_AA );

    // Show Image
    cv::imshow( "image", image );
    cv::waitKey( 0 );

    return 0;
}