Доступ к определенному значению RGB пикселя в openCV
Я искал интернет и stackoverflow тщательно, но я не нашел ответа на мой вопрос:
как я могу получить/установить (оба) значение RGB определенного (заданного координатами x,y) пикселя в OpenCV? Что важно-я пишу на C++, изображение хранится в переменной cv::Mat. Я знаю, что есть оператор IplImage (), но IplImage не очень удобен в использовании-насколько я знаю, он исходит из C API.
Да, я знаю, что уже был этот пиксельный доступ в OpenCV 2.2 резьбы, но речь шла только о черно-белых растровых изображений.
EDIT:
спасибо Вам большое за все ваши ответы. Я вижу, что есть много способов получить/установить значение RGB пикселя. У меня есть еще одна идея от моего близкого друга-Спасибо Беня! Это очень просто и эффективно. Я думаю, что это вопрос вкуса, который вы выбираете.
Mat image;
(...)
Point3_<uchar>* p = image.ptr<Point3_<uchar> >(y,x);
и затем вы можете читать / записывать значения RGB с помощью:
p->x //B
p->y //G
p->z //R
6 ответов:
попробуйте следующее:
cv::Mat image = ...do some stuff...;
image.at<cv::Vec3b>(y,x);
дает вам RGB (он может быть упорядочен как BGR) вектор типа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];
низкоуровневый способ - это прямой доступ к матричным данным. В изображении RGB (который я считаю, что OpenCV обычно хранит как BGR), и предполагая, что ваша переменная cv:: Mat называется
frame
, вы можете получить синее значение в месте (x
,y
) (сверху слева) таким образом:frame.data[frame.channels()*(frame.rows*y + x)];
аналогично, чтобы получить B, G и 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];
обратите внимание, что этот код предполагает, что шаг равен ширине изображения.
кусок кода проще для людей, у которых есть такая проблема. Я делюсь своим кодом, и вы можете использовать его напрямую. Обратите внимание, что магазин в формате OpenCV пикселей, как БГР.
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. }
текущая версия позволяет обработки 3 измерений. Так что для
Mat
объектm
,m.at<uchar>(0,0,0)
должны работать.
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<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; }