2017-10-05 2 views
0

Ich versuche, Histogramme für Materialien in OpenCV 3.2 zu erstellen, bin aber von den HSV-Bereichen verwirrt - sie scheinen nicht mit der Dokumentation übereinzustimmen, oder ich nähere mich ihr falsch.OpenCV cvtColor CV_BGR2HSV CV_32FC3 Sättigungsbereich

// cv::Mat bgrPhoto contains a test image 

cv::Mat3f hsvPhoto; 
bgrPhoto.convertTo(hsvPhoto, CV_32FC3); 
cv::cvtColor(hsvPhoto, hsvPhoto, CV_BGR2HSV, CV_32FC3); 
std::vector<cv::Mat1f> hsvChannels; 
cv::split(hsvPhoto, hsvChannels); 

// Documentation [0.0, 1.0]: measured here Hue to 360.0, Sat to 1.0, Val to 255.0 
double minHue, maxHue, minSat, maxSat, minVal, maxVal; 
cv::minMaxIdx(hsvChannels[0], &minHue, &maxHue, 0, 0); 
cv::minMaxIdx(hsvChannels[1], &minSat, &maxSat, 0, 0); 
cv::minMaxIdx(hsvChannels[2], &minVal, &maxVal, 0, 0); 
+0

OpenCV speichert 'H' Kanalwerte von [0 - 180],' S' und 'V' Werte von [0 - 255]. Konvertieren Sie für "float" die Werte entsprechend. – zindarod

+0

H in [0,360], S, V in [0,1]. Siehe [das Dokument] (http://docs.opencv.org/master/de/d25/imgproc_color_conversions.html#color_convert_rgb_hsv). Außerdem versuchen Sie, ein Ausgabebild mit 21 (CV_32FC3 ergibt 21) Zielkanälen zu erstellen. Verwenden Sie einfach 'cv :: cvtColor (hsvPhoto, hsvPhoto, CV_BGR2HSV);'. Auch 'bgrPhoto.convertTo (hsvPhoto, CV_32F);' da muss nur der Typ und nicht die Tiefe angegeben werden. – Miki

Antwort

1

Wenn Sie Ihr Bild von 8-Bit auf 32-Bit umgewandelt, Sie haben Ihre Werte von [0, 255] auf [0, 1] nicht skaliert. convertTo() konvertiert einfach die Typen; Die Werte werden standardmäßig nicht neu skaliert. Dies wirkt sich auf Ihre Ausgabe aus, da , V, einfach auf max(B, G, R) gesetzt wird (was eine maximale Anzahl von bis zu 255 ergeben wird). Sie werden feststellen, dass in den Dokumenten für cvtColor() für 8-Bit- und 16-Bit-Bilder angegeben ist, dass sie so skaliert werden, dass sie in den [0, 1] -Bereich passen; aber nicht für Float-Bilder. Die Kanäle H und S werden jedoch immer noch auf die richtigen Bereiche skaliert, da sie das Bild mit V skalieren.

Wenn Sie bgrPhoto.convertTo(hsvPhoto, CV_32FC3) tun, müssen Sie durch 255 dividieren, um die Werte in [0, 1] zu setzen. Wenn Sie die docs for convertTo() auschecken, werden Sie bemerken, dass ein drittes Positionsargument gesetzt werden kann, das ein Skalierungsfaktor ist. Wenn Sie einfach bgrPhoto.convertTo(hsvPhoto, CV_32FC3, 1.0/255.0) verwenden, wird, wie in der Dokumentation angegeben, jeder Pixelwert um diesen Faktor skaliert.

Auch Miki Punkt in der Kommentar auf der OP total verrutscht von mir, aber es war ein großer Fang; Überprüfen Sie die docs for cvtColor(); Das vierte Argument ist ein Argument für Anzahl der Zielkanäle, nicht dtype, also cv::cvtColor(hsvPhoto, hsvPhoto, CV_BGR2HSV) ist, was Sie wollen.

+0

Es kann nett sein zu erwähnen, dass Sie dies direkt in der Funktion convertTo tun können: 'bgrPhoto.convertTo (hsvPhoto, CV_32F, 1.0/255.0);' – Miki

+0

Dank @Miki, verlinken einige weitere Dokumentation jetzt. –

+0

Danke Alexander - hervorragende Antwort! – Ike

Verwandte Themen