2016-04-03 52 views
1

内の個別のオブジェクトは、私は3つのピーマンでこのイメージを持つことはできません。はC++ OpenCVのHSVの画像分離

これまでのところ、赤唐辛子を他のものとうまく分離することができるようです。しかし、私は他のペッパーを分ける方法を理解することができないようです。最初のステップとして

#include <opencv2/opencv.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <opencv2/imgcodecs.hpp> 
#include <opencv2/objdetect/objdetect.hpp> 
#include <iostream> 
#include <stdlib.h> 
#include <stdio.h> 
#include <math.h> 
#include <cmath> 
#include <string> 
#include <vector> 

int main(int argc, char *argv[]){ 
    cv::Mat im_in; 
    cv::Mat hsv_in; 
    cv::Mat bgr_in; 
    cv::Mat orig_in; 
    cv::Mat im_o1; 
    cv::Mat im_o2; 
    cv::Mat im_o3; 
    // Read image 
    if (argc<2){ 
    im_in = cv::imread("colorpeppers.jpg"); 
    } 
    if (argc==2){ 
     im_in=cv::imread((argv[1])); 
    } 
    if (argc>2){ 
     std::cout<<"Error! Too many arguments!"<<std::endl; 
    } 
    if (im_in.empty()){ 
     std::cout << "error detected. something went wrong with opening the image. is it empty? exiting"<<std::endl; 
     return -1; 
    } 
    cv::Mat orig_image = im_in.clone(); 
    cv::medianBlur(im_in, im_in, 3); 

    cv::cvtColor(im_in, hsv_in, cv::COLOR_BGR2HSV); 
    cv::namedWindow("Original Image", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Orginal Image", im_in); 

    cv::namedWindow("Orginal Image converted to HSV", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Original Image converted to HSV", hsv_in); 
    cv::Mat lower_red_hue_range; 
    cv::Mat upper_red_hue_range; 
    cv::Mat lower_green_hue_range; 
    cv::Mat upper_green_hue_range; 
    cv::Mat lower_yellow_hue_range; 
    cv::Mat upper_yellow_hue_range; 


    cv::inRange(hsv_in, cv::Scalar(0,100,100), cv::Scalar(10,255,255), lower_red_hue_range); 
    cv::inRange(hsv_in, cv::Scalar(160,100,100),cv::Scalar(179, 255, 255), upper_red_hue_range); 
    cv::inRange(hsv_in, cv::Scalar(0,100,100), cv::Scalar(10,255,255), lower_green_hue_range); 
    cv::inRange(hsv_in, cv::Scalar(50,100,100),cv::Scalar(70,255,255), upper_green_hue_range); 
    cv::inRange(hsv_in, cv::Scalar(0,100,100),cv::Scalar(20,0,0),lower_yellow_hue_range); 
    cv::inRange(hsv_in,cv::Scalar(10,100,100),cv::Scalar(50,110,110),upper_yellow_hue_range); 

    //combining the above 
    cv::Mat red_hue_image=im_in.clone(); 
    cv::Mat green_hue_image=im_in.clone(); 
    cv::Mat yellow_hue_image=im_in.clone(); 
    cv::addWeighted(lower_red_hue_range, 1.0, upper_red_hue_range, 1.0, 0.0, red_hue_image); 
    cv::addWeighted(lower_green_hue_range, 1.0, upper_green_hue_range, 1.0, 0.0, green_hue_image); 
    cv::addWeighted(lower_yellow_hue_range, 1.0, upper_yellow_hue_range, 1.0, 0.0, yellow_hue_image); 
    cv::GaussianBlur(red_hue_image, red_hue_image, cv::Size(9,9), 2, 2); 
    cv::GaussianBlur(green_hue_image, green_hue_image, cv::Size(9,9),2,2); 
    cv::GaussianBlur(yellow_hue_image, yellow_hue_image, cv::Size(9,9),2,2); 

    cv::namedWindow("Threshold lower red image", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Threshold lower red image", lower_red_hue_range); 
    cv::namedWindow("Threshold upper red image", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Threshold upper red image", upper_red_hue_range); 
    cv::namedWindow("Combined Threshold red Images", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Combined Threshold red Images", red_hue_image); 

    cv::namedWindow("Threshold lower green image", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Threshold lower green image", lower_green_hue_range); 
    cv::namedWindow("Threshold upper green image", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Threshold upper green image", upper_green_hue_range); 
    cv::namedWindow("Combined Threshold green Images", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Combined Threshold green Images", green_hue_image); 

    cv::namedWindow("Threshold lower yellow image", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Threshold lower yellow image", lower_yellow_hue_range); 
    cv::namedWindow("Threshold upper yellow image", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Threshold upper yellow image", upper_yellow_hue_range); 
    cv::namedWindow("Combined Threshold yellow Images", cv::WINDOW_AUTOSIZE); 
    cv::imshow("Combined Threshold yellow Images", yellow_hue_image); 



    //cv::Mat redpepper;//=red_hue_image.clone(); 
    //cv::Mat redpepper_hsv; 
    //cvtColor(redpepper, redpepper_hsv,CV_BGR2HSV); 
// for(int i = 0; i < redpepper.rows;i++){ 
    //  for(int j = 0; j <redpepper.cols;j++){ 




    char k; 
    for (int x=1;x<15;x++){ 
     k=cvWaitKey(0); 
    } 

} 
+0

[GIMPの最大RGB(http://docs.gimp.org/en/plug-in-max-rgb。html)は試してみる価値があると思われる – sturkmen

答えて

4

、のk-means clusteringを使用して画像の色数を減らしてみましょう:

は、ここに私のコードです。

次は、HSV空間に画像を変換してみましょうし、個々の色相、彩度、値コンポーネントに分割。

フエ:

色相(colourmapped):

彩度:

値:

色相成分は、アルゴリズムの残りのために十分です。 3つのマスクは、3つの色に適した範囲のピクセルを選択して作成します。

レッド:

黄:

グリーン:

我々は、形態学的変換(拡張、侵食する)を使用して、マスク画像をクリーンアップします。次に、輪郭を検出し、ある閾値(私は5000ピクセルを選択した)以上の領域のみを選択します。我々は、基準を満たす輪郭を塗りつぶして新しいマスクを生成する。

レッド:

黄:

グリーン:

今、私たちは、例えば、輪郭を描くことができます...

レッド:

イエロー:

緑:

コード:

#include <opencv2/opencv.hpp> 

#include <cstdint> 
#include <iostream> 
#include <vector> 

cv::Mat cluster_image(cv::Mat const& img) 
{ 
    int K = 4; 
    int n = img.rows * img.cols; 
    cv::Mat data = img.reshape(1, n); 
    data.convertTo(data, CV_32F); 

    std::vector<int> labels; 
    cv::Mat1f colors; 
    cv::kmeans(data, K, labels 
     , cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10000, 0.0001) 
     , 5, cv::KMEANS_PP_CENTERS, colors); 

    for (int i = 0; i < n; ++i) { 
     data.at<float>(i, 0) = colors(labels[i], 0); 
     data.at<float>(i, 1) = colors(labels[i], 1); 
     data.at<float>(i, 2) = colors(labels[i], 2); 
    } 

    cv::Mat reduced = data.reshape(3, img.rows); 
    reduced.convertTo(reduced, CV_8U); 

    return reduced; 
} 

cv::Mat filter_mask(cv::Mat& img, cv::Mat& mask) 
{ 
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)); 
    cv::Mat filtered; 
    cv::erode(mask, filtered, kernel, cv::Point(-1, -1), 2); 
    cv::dilate(filtered, filtered, kernel, cv::Point(-1, -1), 2); 

    std::vector<std::vector<cv::Point>> contours; 
    std::vector<cv::Vec4i> hierarchy; 

    cv::findContours(filtered, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 

    cv::Mat output_mask = cv::Mat::zeros(mask.size(), CV_8UC1); 

    double const MIN_CONTOUR_AREA(5000.0); 
    for (int i(0); i < contours.size(); ++i) { 
     double area = cv::contourArea(contours[i]); 

     if (area >= MIN_CONTOUR_AREA) { 
      cv::drawContours(output_mask, contours, i, cv::Scalar(255), CV_FILLED); 
     } 
    } 

    cv::dilate(output_mask, output_mask, kernel, cv::Point(-1, -1), 1); 

    return output_mask; 
} 

void highlight_mask(std::string const& filename, cv::Mat& img, cv::Mat& mask) 
{ 
    cv::Mat output = img.clone(); 

    std::vector<std::vector<cv::Point>> contours; 
    std::vector<cv::Vec4i> hierarchy; 
    cv::findContours(mask, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 
    cv::drawContours(output, contours, 0, cv::Scalar(255, 0, 0), 2); 

    cv::imwrite(filename, output); 
} 


int main(int argc, char *argv[]) 
{ 
    cv::Mat orig_image(cv::imread("d:\\code\\shit\\so03\\bin\\runtime\\Debug\\peppers.png")); 
    if (orig_image.empty()) { 
     std::cerr << "Input image empty." << std::endl; 
     return -1; 
    } 

    cv::Mat im_in; 
    cv::medianBlur(orig_image, im_in, 3); 

    cv::Mat clustered = cluster_image(im_in); 
    cv::imwrite("peppers_clustered.png", clustered); 

    cv::Mat hsv_in; 
    cv::cvtColor(clustered, hsv_in, cv::COLOR_BGR2HSV); 

    uint32_t HUE(0), SAT(1), VAL(2); 
    std::vector<cv::Mat> h_s_v(3); 
    cv::split(hsv_in, h_s_v); 
    cv::imwrite("peppers_hue.png", h_s_v[HUE]); 
    cv::imwrite("peppers_sat.png", h_s_v[SAT]); 
    cv::imwrite("peppers_val.png", h_s_v[VAL]); 



    cv::Mat red_mask_a; 
    cv::inRange(h_s_v[HUE], cv::Scalar(2), cv::Scalar(10), red_mask_a); 
    cv::Mat red_mask_b = filter_mask(im_in, red_mask_a); 
    cv::imwrite("peppers_red_mask_a.png", red_mask_a); 
    cv::imwrite("peppers_red_mask_b.png", red_mask_b); 

    cv::Mat yellow_mask_a; 
    cv::inRange(h_s_v[HUE], cv::Scalar(15), cv::Scalar(25), yellow_mask_a); 
    cv::Mat yellow_mask_b = filter_mask(im_in, yellow_mask_a); 
    cv::imwrite("peppers_yellow_mask_a.png", yellow_mask_a); 
    cv::imwrite("peppers_yellow_mask_b.png", yellow_mask_b); 

    cv::Mat green_mask_a; 
    cv::inRange(h_s_v[HUE], cv::Scalar(40), cv::Scalar(50), green_mask_a); 
    cv::Mat green_mask_b = filter_mask(im_in, green_mask_a); 
    cv::imwrite("peppers_green_mask_a.png", green_mask_a); 
    cv::imwrite("peppers_green_mask_b.png", green_mask_b); 

    highlight_mask("peppers_red_out.png", orig_image, red_mask_b); 
    highlight_mask("peppers_yellow_out.png", orig_image, yellow_mask_b); 
    highlight_mask("peppers_green_out.png", orig_image, green_mask_b); 
} 
+0

よくできました。あなたはkmeansのコードを簡略化することができます[少し](@stackoverflow.com/a/34734939/5008845); D – Miki

+0

@Mikiありがとう、コードを更新しました。 –

関連する問題