2016-04-03 6 views
1

Ich habe dieses Bild mit 3 Paprika:Kann nicht trennen Objekte in C++ OpenCV HSV Bildtrennung

Ich brauche das Bild an HSV-Form umzuwandeln und dann jeden Pfeffer in sein eigenes Bild zu trennen.

Bisher scheine ich in der Lage, den roten Pfeffer schön von den anderen zu trennen. Ich kann jedoch nicht herausfinden, wie die anderen Paprikaschoten zu trennen sind.

Hier ist mein Code:

#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

[Max RGB von GIMP] (http://docs.gimp.org/en/plug-in-max-rgb.html) scheint es wert zu versuchen – sturkmen

Antwort

4

Als ersten Schritt wollen wir die Anzahl der Farben im Bild reduzieren k-means clustering verwenden.

Als nächstes wollen wir das Bild zu HSV-Raum umwandeln und spaltete es in einzelne Farbton, Sättigung und Wert-Komponenten.

Hue:

Hue (colourmapped):

Sättigung:

Wert:

Die Farbtonkomponente für den Rest des Algorithmus ausreichend ist. Wir erstellen drei Masken, indem wir Pixel in Bereichen auswählen, die für die drei Farben geeignet sind.

Rot:

Gelb:

Grün:

Wir säubern die Maskenbilder morphologische Transformationen (erodieren aufzuweiten). Als nächstes erkennen wir die Kontur und wählen nur diejenigen aus, deren Fläche größer als ein Schwellenwert ist (ich habe 5000 Pixel ausgewählt). Wir erzeugen neue Masken, indem wir die Konturen füllen, die die Kriterien erfüllen.

Rot:

Gelb:

Grün:

Jetzt können wir zum Beispiel die Konturen zeichnen ...

Rot:

Gelb :

Grün:

Code:

#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

Gut gemacht. Sie können den Kmeans-Code [ein wenig] vereinfachen (http://stackoverflow.com/a/34734939/5008845); D – Miki

+0

@Miki Danke, ich habe den Code aktualisiert. –