2015-03-01 35 views
6

Chcę znaleźć dominujący kolor na obrazie. W tym celu wiem, że powinienem użyć histogramu obrazu. Ale nie jestem pewien formatu obrazu. Który z obrazów rgb, hsv lub gray powinien być użyty?Znajdź dominujący kolor na obrazku

Po obliczeniu histogramu powinienem znaleźć wartość maksymalną na histogramie. W tym celu powinienem znaleźć poniżej maksymalnej wartości binVal dla obrazu hsv? Dlaczego mój wynik zawiera tylko czarny kolor?

float binVal = hist.at<float>(h, s);

EDIT:

Próbowałem poniższy kod. Rysuję histogram h-s. Moje obrazy wyników są tutaj. Nie znajduję niczego po progu binarnym. Może znajdę błędnie maksymalną wartość histogramu.

enter image description here enter image description here

cvtColor(src, hsv, CV_BGR2HSV); 

// Quantize the hue to 30 levels 
// and the saturation to 32 levels 
int hbins = 20, sbins = 22; 
int histSize[] = {hbins, sbins}; 
// hue varies from 0 to 179, see cvtColor 
float hranges[] = { 0, 180 }; 
// saturation varies from 0 (black-gray-white) to 
// 255 (pure spectrum color) 
float sranges[] = { 0, 256 }; 
const float* ranges[] = { hranges, sranges }; 
MatND hist; 
// we compute the histogram from the 0-th and 1-st channels 
int channels[] = {0, 1}; 

calcHist(&hsv, 1, channels, Mat(), // do not use mask 
     hist, 2, histSize, ranges, 
     true, // the histogram is uniform 
     false); 
double maxVal=0; 
minMaxLoc(hist, 0, &maxVal, 0, 0); 

int scale = 10; 
Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3); 
int maxIntensity = -100; 
for(int h = 0; h < hbins; h++) { 
    for(int s = 0; s < sbins; s++) 
    { 
     float binVal = hist.at<float>(h, s); 
     int intensity = cvRound(binVal*255/maxVal); 
     rectangle(histImg, Point(h*scale, s*scale), 
        Point((h+1)*scale - 1, (s+1)*scale - 1), 
        Scalar::all(intensity), 
        CV_FILLED); 
     if(intensity > maxIntensity) 
      maxIntensity = intensity; 
    } 
} 
std::cout << "max Intensity " << maxVal << std::endl; 
Mat dst; 
cv::threshold(src, dst, maxIntensity, 255, cv::THRESH_BINARY); 

namedWindow("Dest", 1); 
imshow("Dest", dst); 
namedWindow("Source", 1); 
imshow("Source", src); 

namedWindow("H-S Histogram", 1); 
imshow("H-S Histogram", histImg); 

Odpowiedz

5

Rozwiązanie

  • Znajdź HS histogramem
  • znaleźć wartość szczytowa H (przy użyciu funkcji minmaxLoc)
  • podziału obrazu 3 kanał (H, s, t)
  • Zastosuj do progu.
  • Tworzenie obrazu o scaleniu 3 kanału
+3

Czy mógłbyś napisać jakiś kod? dzięki –

3

Oto kilka wskazówek, które pomogą Ci zacząć.

  • Wszystkie kanały 3 w RGB przyczynić się do koloru, więc trzeba by jakoś zorientować się, gdzie trzy różne histogramy są na maksimum. (Lub ich suma jest maksymalna, lub cokolwiek innego).
  • HSV ma wszystkie informacje o kolorze (dobrze, odcieniu) w jednym kanale, więc wystarczy wziąć pod uwagę tylko jeden histogram.
  • Skala szarości wyrzuca wszystkie informacje o kolorach, więc jest praktycznie bezużyteczna dla koloru .

Spróbuj przekonwertować do HSV, a następnie obliczyć histogram na kanale H.

Tak jak mówisz, chcesz znaleźć maksymalną wartość na histogramie. Ale:

  • Możecie rozważyć zakres wartości, a nie tylko jednego, powiedzmy z 20-40 zamiast tylko 30. Wypróbuj różne rozmiary zasięgu.
  • Pamiętaj, że odcień jest okrągły, więc H=0 i H=360 są takie same.
  • Spróbuj wykreślić następujący histogram:
    http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html
    , aby sprawdzić, czy Twoje wyniki mają sens.
  • Jeśli używasz zakresu odcieni i znajdziesz zakres, który jest maksymalny, możesz albo użyć środka tego zakresu jako dominującego koloru, albo możesz znaleźć średnią kolorów z tego zakresu i użyć tego.

    Spróbuj. Grać.

8

Alternatywnie można spróbować podejścia k-means. Calculate k clusters z k ~ 2..5 i weź środek ciężkości największej grupy jako dominujący kolor.

docu pyton z OpenCV ma illustrated example który pobiera kolor dominujący (y) całkiem dobrze:

+0

powinny znaleźć największy obszar koloru bardzo fastly, a mój obraz jest bardzo duże. Czy ta metoda jest skuteczna w tym zadaniu? – zumma

+0

hmm, dziękuję za porady. Nie umiem tego używać. – zumma

+0

Nie, najprawdopodobniej jest wolniejszy niż prosty histogram (dokładna wersja jest nawet NP-zupełna). Ale ponieważ to zadanie wykonuje silną redukcję wymiarów z "N" pikseli do jednego koloru, najprawdopodobniej po prostu nie bierze się pod uwagę wszystkich pikseli, tj. Najpierw pod-próbkę obrazu (niezależnie od metody, której używasz do rzeczywistego określenia kolor później). – mbschenkel