Opencv Get Pixel Channel Value from Mat Image

OpenCV get pixel channel value from Mat image

Assuming the type is CV_8UC3 you would do this:

for(int i = 0; i < foo.rows; i++)
{
for(int j = 0; j < foo.cols; j++)
{
Vec3b bgrPixel = foo.at<Vec3b>(i, j);

// do something with BGR values...
}
}

Here is the documentation for Vec3b. Hope that helps! Also, don't forget OpenCV stores things internally as BGR not RGB.

EDIT :

For performance reasons, you may want to use direct access to the data buffer in order to process the pixel values:

Here is how you might go about this:

uint8_t* pixelPtr = (uint8_t*)foo.data;
int cn = foo.channels();
Scalar_<uint8_t> bgrPixel;

for(int i = 0; i < foo.rows; i++)
{
for(int j = 0; j < foo.cols; j++)
{
bgrPixel.val[0] = pixelPtr[i*foo.cols*cn + j*cn + 0]; // B
bgrPixel.val[1] = pixelPtr[i*foo.cols*cn + j*cn + 1]; // G
bgrPixel.val[2] = pixelPtr[i*foo.cols*cn + j*cn + 2]; // R

// do something with BGR values...
}
}

Or alternatively:

int cn = foo.channels();
Scalar_<uint8_t> bgrPixel;

for(int i = 0; i < foo.rows; i++)
{
uint8_t* rowPtr = foo.row(i);
for(int j = 0; j < foo.cols; j++)
{
bgrPixel.val[0] = rowPtr[j*cn + 0]; // B
bgrPixel.val[1] = rowPtr[j*cn + 1]; // G
bgrPixel.val[2] = rowPtr[j*cn + 2]; // R

// do something with BGR values...
}
}

How access to a pixel value in a binary Mat image?

For Mat element access you can refer OpenCV official Doc and these link1, link2 might be helpful

And here is a simple code that access pixel value according to your mouse position and display the pixel value.

#include <iostream>
#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;
Mat image, src;
char window_name[20]="Pixel Value Demo";

void onMouse( int event, int x, int y, int f, void* ){
image=src.clone();
Vec3b pix=image.at<Vec3b>(y,x);
int B=pix.val[0];
int G=pix.val[1];
int R=pix.val[2];


char name[30];
sprintf(name,"R=%d",R);
putText(image,name, Point(10,130) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );

sprintf(name,"G=%d",G);
putText(image,name, Point(10,170) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );

sprintf(name,"B=%d",B);
putText(image,name, Point(10,210) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );

sprintf(name,"X=%d",x);
putText(image,name, Point(10,300) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );

sprintf(name,"Y=%d",y);
putText(image,name, Point(10,340) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );
imshow( window_name, image );
}



int main( int argc, char** argv )
{
namedWindow( window_name, CV_WINDOW_AUTOSIZE );

src = imread( "ball.jpg");
imshow( window_name, src );

setMouseCallback( window_name, onMouse, 0 );

waitKey(0);

return 0;
}

Edit:-

For binary image you can access pixel value with Mat::at(row,col) method.

In below example show how to do this. Here the image is of type uchar.

 Mat src(480,640,CV_8UC1,Scalar(0));
circle(src,Point(src.cols/2,src.rows/2),100,Scalar(255),-1,8,0);

int pix=(int)src.at<uchar>(src.rows/2,src.cols/2);
cout<<pix<<endl;

How to make getting a pixel value independent of the cv::Mat type?

Drop the use of cv::Mat - where you have to call type() method (at runtime) to get the type of values stored by mat, and instead that just start using templated version of mat class: it is cv::Mat_<Type> and write more generic code.

Then you could write only one function template to read mat pixels:

template<class T>
T access(cv::Mat_<T> const& img, int r, int c) {
return img(r,c);
}

More about cv::Mat_ here.

How to get pixel value of Mat image with webcam capture in OpenCV

The output image of distanceTransform is of type CV_32FC1, so each pixel is of type float. To access the pixel value, you have to do the following:

if(distanceTr.at<float>(0,0) == 0)
{
cout<<1;
}

In the opencv documentation, the description of each function parameter is given, like what is the size and type of the image etc.

Using get() and put() to access pixel values in OpenCV for Java

It was happening because of byte() casting. I changed the data type of mat image in second case to *CV_64FC3* so that I can use double[] instead of byte[] and it solved the problem.

Mat A = Highgui.imread(image_addr); //"image_addr" is the address of the image
Mat C = A.clone();
A.convertTo(A, CvType.CV_64FC3); // New line added.
int size = (int) (A.total() * A.channels());
double[] temp = new double[size]; // use double[] instead of byte[]
A.get(0, 0, temp);
for (int i = 0; i < size; i++)
temp[i] = (temp[i] / 2); // no more casting required.
C.put(0, 0, temp);

FYI, I also did some time measurement and using second method is way faster than first method.

How to get pixel value from the contoured image with mask?

A few things:

  • Your variables names and Mat types are at least confusing. Use proper names for the variables, and use Mat_<T> whenever possible (I'd say always).
  • To get the mean you should divide by the number of pixels in the mask, not by total number of pixels.
  • you should consider using cv::mean
  • you need cv::waitKey() to actually see your cv::imshow

Check the code:

#include <opencv2\opencv.hpp>

int main()
{
cv::Mat3b star = cv::imread("path/to/image");
cv::imshow("Original", star);

cv::Mat3b hsv;
cv::cvtColor(star, hsv, cv::COLOR_BGR2HSV);

cv::Mat1b mask;
cv::inRange(hsv, cv::Scalar(29, 220, 220), cv::Scalar(30, 255, 255), mask);
cv::imshow("mask", mask);

// Change to 'false' to see how to use the 'cv::mask' approach
if (true)
{
double blue, green, red = 0.0;
int counter = 0;
for (int r = 0; r < star.rows; r++)
{
for (int c = 0; c < star.cols; c++)
{
if (mask(r, c) > 0)
{
++counter;
blue += star(r, c)[0];
green += star(r, c)[1];
red += star(r, c)[2];
}
}
}

// Avoid division by 0
if (counter > 0)
{
blue /= counter;
green /= counter;
red /= counter;
}

std::cout << "$$ Red(R), Green(G), Blue(B) $$" << " \n\n";
std::cout << "avg_R: " << red << " \n";
std::cout << "avg_G: " << green << " \n";
std::cout << "avg_B: " << blue << " \n\n";
}
else
{
cv::Scalar mean_value = cv::mean(star, mask);
double blue = mean_value[0];
double green = mean_value[1];
double red = mean_value[2];

std::cout << "$$ Red(R), Green(G), Blue(B) $$" << " \n\n";
std::cout << "avg_R: " << red << " \n"; // red value
std::cout << "avg_G: " << green << " \n"; // green value
std::cout << "avg_B: " << blue << " \n\n"; // blue value
}
cv::waitKey();
}

c++ and opencv get and set pixel color to Mat

You did everything except copying the new pixel value back to the image.

This line takes a copy of the pixel into a local variable:

Vec3b color = image.at<Vec3b>(Point(x,y));

So, after changing color as you require, just set it back like this:

image.at<Vec3b>(Point(x,y)) = color;

So, in full, something like this:

Mat image = img;
for(int y=0;y<img.rows;y++)
{
for(int x=0;x<img.cols;x++)
{
// get pixel
Vec3b & color = image.at<Vec3b>(y,x);

// ... do something to the color ....
color[0] = 13;
color[1] = 13;
color[2] = 13;

// set pixel
//image.at<Vec3b>(Point(x,y)) = color;
//if you copy value
}
}


Related Topics



Leave a reply



Submit