Ich habe das Internet und den Stackoverflow gründlich durchsucht, aber keine Antwort auf meine Frage gefunden:
Wie kann ich (beide) RGB-Werte bestimmter (durch x, y-Koordinaten gegebener) Pixel in OpenCV abrufen / einstellen? Was wichtig ist - ich schreibe in C ++, das Bild wird in der Variablen cv :: Mat gespeichert. Ich weiß, dass es einen IplImage () -Operator gibt, aber IplImage ist nicht sehr benutzerfreundlich - soweit ich weiß, stammt es von der C-API.
Ja, mir ist bekannt, dass es diesen Pixelzugriff bereits im OpenCV 2.2- Thread gab, aber es ging nur um Schwarz-Weiß-Bitmaps.
BEARBEITEN:
Vielen Dank für all Ihre Antworten. Ich sehe, dass es viele Möglichkeiten gibt, den RGB-Wert eines Pixels zu erhalten / einzustellen. Ich habe noch eine Idee von meinem engen Freund - danke Benny! Es ist sehr einfach und effektiv. Ich denke, es ist Geschmackssache, welche Sie wählen.
Mat image;
(...)
Point3_<uchar>* p = image.ptr<Point3_<uchar> >(y,x);
Und dann können Sie RGB-Werte lesen / schreiben mit:
p->x //B
p->y //G
p->z //R
Der einfache Weg wäre, direkt auf die Matrixdaten zuzugreifen. In einem RGB-Bild (von dem ich glaube, dass OpenCV es normalerweise als BGR speichert) und unter der Annahme, dass Ihre Variable cv :: Mat aufgerufen wird
frame
, können Sie den blauen Wert an Position (x
,y
) (von oben links) folgendermaßen erhalten:Um B, G und R zu erhalten:
uchar b = frame.data[frame.channels()*(frame.cols*y + x) + 0]; uchar g = frame.data[frame.channels()*(frame.cols*y + x) + 1]; uchar r = frame.data[frame.channels()*(frame.cols*y + x) + 2];
Beachten Sie, dass dieser Code davon ausgeht, dass der Schritt der Breite des Bildes entspricht.
quelle
frame.data[frame.channels()*(frame.cols*y + x)];
?Ein Stück Code ist für Leute, die ein solches Problem haben, einfacher. Ich teile meinen Code und Sie können ihn direkt verwenden. Bitte beachten Sie, dass OpenCV Pixel als BGR speichert.
cv::Mat vImage_; if(src_) { cv::Vec3f vec_; for(int i = 0; i < vHeight_; i++) for(int j = 0; j < vWidth_; j++) { vec_ = cv::Vec3f((*src_)[0]/255.0, (*src_)[1]/255.0, (*src_)[2]/255.0);//Please note that OpenCV store pixels as BGR. vImage_.at<cv::Vec3f>(vHeight_-1-i, j) = vec_; ++src_; } } if(! vImage_.data ) // Check for invalid input printf("failed to read image by OpenCV."); else { cv::namedWindow( windowName_, CV_WINDOW_AUTOSIZE); cv::imshow( windowName_, vImage_); // Show the image. }
quelle
Die aktuelle Version ermöglicht es der
cv::Mat::at
Funktion, 3 Dimensionen zu verarbeiten . Also für einMat
Objektm
,m.at<uchar>(0,0,0)
sollte funktionieren.quelle
at
funktioniert diese Version von nicht auf Mehrkanal-Mat. Trotz der Tatsache, dass die zweidimensionale Mehrkanal-Matte das gleiche Speicherlayout wie die dreidimensionale einkanalige Matte hat, löst die Methode aufgrund der Unterschiede im Mat-Header eine Ausnahme aus.uchar * value = img2.data; //Pointer to the first pixel data ,it's return array in all values int r = 2; for (size_t i = 0; i < img2.cols* (img2.rows * img2.channels()); i++) { if (r > 2) r = 0; if (r == 0) value[i] = 0; if (r == 1)value[i] = 0; if (r == 2)value[i] = 255; r++; }
quelle
const double pi = boost::math::constants::pi<double>(); cv::Mat distance2ellipse(cv::Mat image, cv::RotatedRect ellipse){ float distance = 2.0f; float angle = ellipse.angle; cv::Point ellipse_center = ellipse.center; float major_axis = ellipse.size.width/2; float minor_axis = ellipse.size.height/2; cv::Point pixel; float a,b,c,d; for(int x = 0; x < image.cols; x++) { for(int y = 0; y < image.rows; y++) { auto u = cos(angle*pi/180)*(x-ellipse_center.x) + sin(angle*pi/180)*(y-ellipse_center.y); auto v = -sin(angle*pi/180)*(x-ellipse_center.x) + cos(angle*pi/180)*(y-ellipse_center.y); distance = (u/major_axis)*(u/major_axis) + (v/minor_axis)*(v/minor_axis); if(distance<=1) { image.at<cv::Vec3b>(y,x)[1] = 255; } } } return image; }
quelle