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.
Related
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.
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
CacheKey method of QImage returns not really a plain hash of image. Does anyone know, what the upper 32 bits mean? And can I really ignore them when comparing two images? (Compare only the lower 32 bits?)
For illustration only, this code reading the same image multiple times (yet storing them in different QImage objects):
printf("%llx\n",QImage("image.png").cacheKey());
printf("%llx\n",QImage("image.png").cacheKey());
printf("%llx\n",QImage("image.png").cacheKey());
returns this?
144300000002
144400000002
144500000002
or this? (seems like the upper 32 bits depend on current memory position)
140800000002
140900000002
140a00000002
No, you can't use any part of the cacheKey to compare image content, it only exists to make sure an image hasn't changed since the last cacheKey value was taken. It identifies the buffer and changes whenever any non-const function of the QImage is called.
But as the name of the cacheKey property implies, you can use it as a key for a QCache<qint64, QByteArray> where you would store the actual hash of the image that you would only recalculate with QCryptographicHash only if the image was changed (= only if it isn't already in the cache).
Also QImage doesn't use a cache like QPixmap for reading an image, so reading 3 times the same image file will allocate 3 distinct buffers, each time with a different cacheKey. To avoid calculating the hashes each time, you should take a look at the source code of the QPixmap::load function.
The upper 32 bit depend on nothing, but the 32 bit of the previous image. It is a serial number, which in incremented with each new QImage.
Looking at the source for QImage :
qint64 QImage::cacheKey() const
{
if (!d)
return 0;
else
return (((qint64) d->ser_no) << 32) | ((qint64) d->detach_no);
}
looks like the upper 32 bits are d->ser_no which is initialized with QImageData:
QBasicAtomicInt qimage_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1);
QImageData::QImageData()
: ref(0), width(0), height(0), depth(0), nbytes(0), data(0),
#ifdef QT3_SUPPORT
jumptable(0),
#endif
format(QImage::Format_ARGB32), bytes_per_line(0),
ser_no(qimage_serial_number.fetchAndAddRelaxed(1)),
detach_no(0),
dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false),
is_cached(false), paintEngine(0)
{
}
And it looks like QBasicAtomicInt is an atomic reference counter (see here). So it looks like every new image will have a different upper 32 bits in the cachekey value unless you copy it rather than create it anew.
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.
reading the docs i see that the glGetTexImage2d() function has a 'type' parameter.
The docs say that the type parameter "specifies the data type of the pixel data" and gives some examples of types such as GL_INT, GL_BYTE, etc.
but what does it mean precisely when the image format is GL_RGBA and GL_INT ? is it an int for each channel? or an int for the whole color? and if it's an int for th whole color, then isn't that really the same as GL_BYTE ? since there's 4 bytes in an int which makes each channel a byte each
It's an int per channel. RGBA means each pixel has R, G, B and A ints (if you set it to int) in the data-array you're giving it. RBGA (if it exists, not sure of that) would also mean four ints, but ordered differently. RGB would mean just three (no alpha channel).
The type parameter specifies the effective type of the data inside the buffer you're sending to OpenGL.
The aim here is that OpenGL is going to walk in your buffer, and want to know how much elements are present ( width * height * internalformat ) and their size & interpretation (type).
For instance, if you are to provide an array of unsigned ints containing red/green/blue/alpha channels (in this order), you'll need to specify:
target: GL_TEXTURE_2D
level: 0 (except if you use mipmaps)
internalformat: 4 because you have red, green, blue and alpha
width: 640
height: 480
border: 0
internal format: GL_RGBA to tell opengl the order of our channels, and what they mean
type: GL_UNSIGNED_INT will let opengl know the type of elements inside our array
pixels: a pointer to your array