web-dev-qa-db-fra.com

Accéder à certaines valeurs RVB de pixels dans openCV

J'ai cherché Internet et stackoverflow à fond, mais je n'ai pas trouvé de réponse à ma question:

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

Oui, je sais qu'il y avait déjà ce fil Accès aux pixels dans OpenCV 2.2 , mais il ne s'agissait que de bitmaps en noir et blanc.

EDIT:

Merci beaucoup pour toutes vos réponses. Je vois qu'il y a plusieurs façons d'obtenir/définir la valeur de pixel RVB. J'ai encore une 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_<uchar>* p = image.ptr<Point3_<uchar> >(y,x);

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

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

Essayez ce qui suit:

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

image.at<cv::Vec3b>(y,x); vous donne le vecteur RVB (il peut être ordonné en tant que BGR) de type cv::Vec3b

image.at<cv::Vec3b>(y,x)[0] = newval[0];
image.at<cv::Vec3b>(y,x)[1] = newval[1];
image.at<cv::Vec3b>(y,x)[2] = newval[2];
90
Boaz

La méthode la plus simple consiste à accéder directement aux données de la matrice. Dans une image RVB (que OpenCV stocke généralement sous le nom BGR), et en supposant que votre variable cv :: Mat s'appelle frame, vous pourriez obtenir la valeur bleue à l'emplacement (x, y) (en haut à gauche) de cette façon:

frame.data[frame.channels()*(frame.cols*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.

16
aardvarkk

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<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.
}
2
ShannonLiu

La version actuelle permet à la fonction cv::Mat::at De gérer dimensions . Donc, pour un objet Mat, m, m.at<uchar>(0,0,0) devrait fonctionner.

0
Jacob
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++;
}
0
Saef Myth