Acessando determinado valor RGB de pixel em openCV

Eu pesquisei internet e stackoverflow completamente, mas eu não encontrei resposta para a minha pergunta:

Como posso obter / definir (ambos) o valor RGB de determinados pixels (dados por x, y coordenadas) no OpenCV? O que é importante – estou escrevendo em C ++, a imagem é armazenada na variável cv :: Mat. Eu sei que há um operador IplImage (), mas IplImage não é muito confortável em usar, tanto quanto eu sei que vem da API C.

Sim, estou ciente de que já havia esse access ao Pixel no encadeamento OpenCV 2.2 , mas era apenas sobre bitmaps em preto-e-branco.

EDITAR:

Muito obrigado por todas as suas respostas. Eu vejo que existem muitas maneiras de obter / definir o valor RGB do pixel. Eu tenho mais uma ideia do meu amigo íntimo, obrigado Benny! É muito simples e eficaz. Eu acho que é uma questão de gosto qual você escolhe.

Mat image; 

(…)

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

E então você pode ler / gravar valores RGB com:

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

Tente o seguinte:

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

image.at(y,x); lhe dá o vetor RGB (pode ser pedido como BGR) do tipo cv::Vec3b

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

A maneira de baixo nível seria acessar os dados da matriz diretamente. Em uma imagem RGB (que acredito que o OpenCV normalmente armazena como BGR), e assumindo que sua variável cv :: Mat é chamada de frame , você pode obter o valor azul na localização ( x , y ) (do topo esquerdo) desta forma:

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

Da mesma forma, para obter B, G e 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]; 

Note que este código assume que o stride é igual à largura da imagem.

Um pedaço de código é mais fácil para pessoas que têm esse problema. Eu compartilho meu código e você pode usá-lo diretamente. Por favor, note que o OpenCV armazena pixels como 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. } 

A versão atual permite que a function cv::Mat::at manipule 3 dimensões . Portanto, para um object Mat m , m.at(0,0,0) deve funcionar.

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