Accediendo a cierto valor de píxel RGB en openCV

He buscado exhaustivamente Internet y stackoverflow, pero no he encontrado respuesta a mi pregunta:

¿Cómo puedo obtener / establecer (ambos) el valor RGB de cierto pixel (dado por coordenadas x, y) en OpenCV? Lo que es importante, estoy escribiendo en C ++, la imagen está almacenada en cv :: Variable Mat. Sé que hay un operador IplImage (), pero IplImage no es muy cómodo de usar, por lo que sé que proviene de C API.

Sí, soy consciente de que ya existía este acceso a píxeles en el hilo OpenCV 2.2 , pero solo se trataba de bitmaps en blanco y negro.

EDITAR:

Muchas gracias por todas sus respuestas. Veo que hay muchas formas de obtener / establecer el valor RGB de píxel. Recibí una idea más de mi amigo cercano, ¡gracias Benny! Es muy simple y efectivo. Creo que es una cuestión de gusto cuál elegir.

Mat image; 

(…)

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

Y luego puede leer / escribir valores RGB con:

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

Pruebe lo siguiente:

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

image.at(y,x); le proporciona el vector RGB (se puede pedir como BGR) de tipo cv::Vec3b

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

El camino de bajo nivel sería acceder directamente a los datos de la matriz. En una imagen RGB (que creo que OpenCV normalmente almacena como BGR), y suponiendo que su variable cv :: Mat se llama frame , puede obtener el valor azul en la ubicación ( x , y ) (desde la esquina superior izquierda) de esta manera:

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

Del mismo modo, para obtener B, G y 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]; 

Tenga en cuenta que este código asume que la zancada es igual al ancho de la imagen.

Una pieza de código es más fácil para las personas que tienen ese problema. Comparto mi código y puedes usarlo directamente. Tenga en cuenta que los píxeles de la tienda OpenCV 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. } 

La versión actual permite que la función cv::Mat::at maneje 3 dimensiones . Entonces, para un objeto Mat m , m.at(0,0,0) debería 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; }