The best access pixel value method to an Mat binary image? - c++

I want to ask a question: I have to check the value time by time of a pixel (X,Y) in a binary thresholded OpenCV Mat image.
I have to check if the pixel at the X,Y that I want to verify is black or white (0 or 255)...how is the best method to do this thing?
I have searched and read about direct method (Get2D) or with pointers..but it isn't so clear for me...Image are binary, thresholded and eroded/dilated before...
Can someone post me an example of code of function that I've to use to do this thing?

If you check the same pixel all the time, do it as #Xale says:
mat.at<unsigned char>(x,y) // assuming your type is CV_8U
If you have to do it for several pixels, get the offset of the row first and access the column later:
unsigned char *row = mat.ptr<unsigned char>(y);
// access now row[x1], row[x2]...
There is one more option that is only valid if you only want a single pixel and if all the operations on the image are done on the same allocated memory (it depends on your code and the opencv functions you call). In that case, you can get the pointer to that pixel once, and access it when you need:
unsigned char *px = mat.ptr<unsigned char>(y) + x;
...
unsigned char current_value = *px;

You have to refer to this nice tutorial for accessing cv::Mat elements:
http://docs.opencv.org/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html
There are different ways to achieve it. The main problem when you access the element is to understand the data type of the matrix/image. In you case, if the mat is a binary black and white probab it is of the type CV_8U, and my advice is always check for the type to be sure. Plus, playing with types get you more control on the knowledge of what you're dealing with.
One of the easiest method for accessing pixels is cv::Mat::at that is a template method, and it needs to specify the type, that, if your mati is CV_8U is uchar.

the easy way:
int n = cv::countNonZero(binary_mat);
the hard way:
for ( int i=0; i<mat.rows; i++ )
{
for ( int j=0; j<mat.cols; j++ )
{
uchar pix = mat.at<uchar>(i,j);
...

Hers is a link to another stackoverflow answer. Anyway short answer is
mat.at<Type>(x,y)
where Typeis the type of data stored in the matrixelements. In your case unsigned char

Related

convert unsigned short mat to vector in opencv

I load a depth image in opencv with
cv::Mat depth = cv::imread("blabla.png",CV_LOAD_IMAGE_UNCHANGED);
then get a subimage of it with
cv::Mat sub_image= depth(cv::Rect( roi_x,roi_y,roi_size,roi_size)).clone();
now I want to convert that sub_image into a vector
I try with
std::vector<uchar> array;
array.assign(sub_image.datastart,sub_image.dataend);
that found here in StackOverflow in a similar question but it seems it doesnt work properly.
The size of array after assignment isnt roi_size * roi_size,
but instead roi_size*roi_size*2
Is something wrong with the type of vector?? I also tried various other types like double, float, int, etc
The type of the depth image is unsigned short right??
Edit:
array fills properly (correct size roi_size*roi_size) when I normalize the depth image
cv::Mat depthView;
cv::normalize(depth, depthView, 0, 255, cv::NORM_MINMAX,CV_8UC1);
but thats not what I want to do
Your observation of roi_size*roi_size*2 was due to the fact that the depth image is of short type which is each of size 2 bytes. You are trying to push this image data to an array of type unsigned char.
Make the vector type to short and you will find that the array size got back to roi_size*roi_size as expected. The values too would be what you expected it to be.
Have you tried checking, which type of image you read, i.e. with depth.type() == CV_8UC1 for 8-bit uchar with 1 channel.
Maybe your image was interpreted defferently.
Have you tried reading the image with the flag CV_LOAD_IMAGE_GRAYSCALE instead of CV_LOAD_IMAGE_UNCHANGED?
Thanks for all the help guys,
I think I managed to solve the problem.
I changed the code for the array assignment to this
std::vector<unsigned short> array(sub_image.begin<unsigned short>(),sub_image.end<unsigned short>());
and now the size is correct roi_size*roi_size
thanks again for the help.

How to print all the raw data of QImage for comparisons in the memory?

I have two QImage objects which should be equal but the result of QImage::operator== is false. So I want to print all the raw data of the two objects for the comparison. How to do that? Can it be done with qDebug()?
I suggest you write a function to compare the two images, byte by byte, and return the offset where they are different.
Comparing image data by hand is often tedious and can lead to mistakes.
If You want to print values of each pixel, then use bits() method of QImage to get pointer to all pixel values in unsigned char and just print them in for loop. For example if You have 32-bit pictures then in table returned by bits() You will have 4 values for each pixel (Red, Green, Blue, Alpha) and to know how many of those You have just use width()*height()*4 (if it's 32-bit depth). Or You can compare every single pixel instead of printing and return only those which differ.
Using qDebug() << QImage() will print out something like QImage(QSize(0, 0) ).
You could use the const uchar * QImage::constBits() function to get a pointer to the first pixel data, and then iterate through the pixel data, printing the values.

OpenCV Image data type conversion in C++

I am trying to convert an Image data from char to double in C++, for example
Mat img = imread(image_file);
Mat img_double;
img.convertTo(img_double, CV64FC3);
Then I think img_double should store the image data in DOUBLE, and I tried img_double.depth() it shows as 6, which is correct. However, how do I access that DOUBLE data?? img_double.data is still in uchar* type. Can anybody help me? thanks!
C/C++ uses unsigned char as the generic data type for a bunch of bytes.
Hence, having an uchar data pointer in cv::Mat avoids to change the declaration of thsi pointer for each type of image, thus avoiding subclassing cv::Mat and allowing direct data transfer via memcpy or pointer affectation.
Casting is then used to return the data type desired by the user of the library.
Note that OpenCV 2.x provides you th etemplated function cv::Mat::ptr<type>(ìnt rowIndex) to obtain a pointer to th ebeginning of a given row.
For example, a pointer to the beginning of row 6 of a grey image of double data type is done by:
double *rowPtr = my_mat.ptr<double>(6)
You can access data of img_double in the following manner.
img_double.at<Vec3d>(i, j)[0] -> B
img_double.at<Vec3d>(i, j)[1] -> G
img_double.at<Vec3d>(i, j)[2] -> R
so to access pixel values of img and double_img, you can do something like this
printf("%d %d %d\n", img.at<Vec3b>(0, 0)[0], img.at<Vec3b>(0, 0)[1], img.at<Vec3b>(0, 0)[2]);
printf("%f %f %f\n", double_img.at<Vec3d>(0, 0)[0], double_img.at<Vec3d>(0, 0)[1], double_img.at<Vec3d>(0, 0)[2]);
This might be more helpful.
img_data is always uchar (it's bytes - that's all memory is) the image type just keeps track of what type and range you want to think of it as.
Opencv CV is/was a C library at heart so there is no way to have the data actually converted automatically to other types, but you can always just cast it.

How to determine the type of data in a cv::Mat converted to grayscale

I'm not sure where to find this information.
I loaded in a .jpg and converted it to grayscale with cv::cvtColor(*input_image_grayscale, *input_image_grayscale, CV_BGR2GRAY);
I then try to reference a pixel with input_image_grayscale->at<float>(row, col) but get an assertion error. How do I determine the right type of data (it's clearly not float) to dereference this? Thanks
For reference, I ran input_image_grayscale->type() and got 0.
The value returned by type is just an integer that OpenCV declares with a preprocessor define. You can check it in a switch statement like this:
switch( matrixType )
{
case CV_8UC1:
.... check for other types
}
The 8U, in that example refers to an unsigned char, and C1 refers to a single channel image. CV_8UC1 is defined as 0, so that is your Mat's type and you should use unsigned char for your reference type.
You can also use the function Mat::depth, to return the type of the size of a single matrix element, because you already know it is a single channel image since it is grayscale.

How to build a QImage from known pixel values

I know the height and width, as well as each pixel value (from x,y location) that I want a QImage to be. How can I build a QImage knowing these values?
The second argument to setPixel() is a 24bit RGB value in a single int you can use the QRgb macros to construct it or just (red<<16) + (green << 8) + blue
But unless it's a very small image it will take a long time to call setPixel().
If you have the data I would call Qimage::bits() to get an unsigned pointer to the QImage data and just set the R,G,B values directly for each pixel or use memcpy()
You simply create the object (eg, new QImage(640, 480);) and then use setPixel to change each pixel in the image to the value you want it to be.