Accéder à certains pixels de valeur RVB en openCV

J’ai fait une recherche approfondie sur internet et stackoverflow, mais je n’ai pas trouvé de réponse à ma question:

Comment puis-je obtenir / définir (les deux) la valeur RVB de certains pixels (donnés par les coordonnées x, y) dans OpenCV? Ce qui est important – J’écris en C ++, l’image est stockée dans la variable cv :: Mat. Je sais qu’il y a un opérateur IplImage (), mais IplImage n’est pas très confortable à utiliser, pour autant que je sache, il provient de l’API C.

Oui, je sais qu’il y avait déjà cet access aux pixels dans le thread OpenCV 2.2 , mais il ne s’agissait que de bitmaps en noir et blanc.

MODIFIER:

Merci beaucoup pour toutes vos réponses. Je vois qu’il existe plusieurs façons d’obtenir / de définir la valeur RVB du pixel. J’ai eu une autre idée de mon ami proche – merci Benny! C’est très simple et efficace. Je pense que c’est une question de goût que vous choisissez.

Mat image; 

(…)

 Point3_* p = image.ptr<Point3_ >(y,x); 

Et puis vous pouvez lire / écrire des valeurs RVB avec:

 p->x //B p->y //G p->z //R 

Essayez ce qui suit:

 cv::Mat image = ...do some stuff...; 

image.at(y,x); vous donne le vecteur RGB (il pourrait être commandé en BGR) de type cv::Vec3b

 image.at(y,x)[0] = newval[0]; image.at(y,x)[1] = newval[1]; image.at(y,x)[2] = newval[2]; 

La méthode de bas niveau serait d’accéder directement aux données de la masortingce. Dans une image RVB (que OpenCV considère généralement comme BGR), et en supposant que votre variable cv :: Mat s’appelle frame , vous pouvez obtenir la valeur bleue à l’emplacement ( x , y ) (en haut à gauche) de cette façon:

 frame.data[frame.channels()*(frame.rows*y + x)]; 

De même, pour obtenir B, G et R:

 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]; 

Notez que ce code suppose que la foulée est égale à la largeur de l’image.

Un morceau de code est plus facile pour les personnes qui ont un tel problème. Je partage mon code et vous pouvez l’utiliser directement. Veuillez noter que OpenCV stocke les pixels en tant que BGR.

 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(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. } 

La version actuelle permet à la fonction cv::Mat::at de gérer 3 dimensions . Donc, pour un object Mat m , m.at(0,0,0) devrait fonctionner.

 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++; } 
 const double pi = boost::math::constants::pi(); 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(y,x)[1] = 255; } } } return image; }