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.
Related
I've a c++ function (wrapped in obj-c files in Xcode):
int64_t* findEdges(int64_t* pixels, int width, int height);
that I'd like to call from Swift 3 and pass in a buffer full of picture data. After hunting around I'm calling it with:
var ptr = (NSData(data: imageRep.tiffRepresentation!).bytes).bindMemory(to: Int64.self, capacity: 4 * height * width).pointee
let processor = findEdges(&ptr, width, height)
But after accessing around 30 or 40 addresses in the c++ file I get a EXC_BAD_ACCESS crash.
Is the problem that I'm passing unsafe pointers from Swift? What would be the correct call procedure?
Here are at least some of the problems with this approach. There may be more, since I don't know what exactly findEdges() input means and how that function finds the edges.
NSData's bytes property is a raw pointer not bound to any type. The call to bindMemory then indicates that the NSData's content is to be treated as a buffer of 4 * height * width of 8-byte integers, i.e. a buffer of 32 * height * width bytes. I haven't worked with the TIFF format lately, but I strongly suspect that a TIFF representation of an image of width x height size would contain a lot less bytes than that, so even if the buffer was successfully passed to findEdges, trying to treat it as much larger than it is would lead to an access violation.
The first 8 bytes of the image's TIFF representation are treated as an Int64 and copied to the ptr variable, the address of which is then passed to findEdges, which treats it as the address of a buffer of 4 * height * width Int64 values. However, only the 1st Int64 in the buffer has anything to do with the image (it contains the first 8 bytes of its TIFF representation). When findEdges accesses the 2nd Int64 in the pixels array, it accesses memory having nothing to do with the image. It may be lucky accessing a few more (garbage) Int64 values, but will eventually try to access something it can't.
Solution depends on whether pixels required by findEdges contains the exact same byte sequence as the image's TIFF representation, or some transformation is required. In other words, can we say that the first 8 bytes of the TIFF representation form the first element of the pixels Int64 array, the 2nd 8 bytes - the 2nd element etc.
Assuming the buffer can be passed to the C++ function as is, here is a brief simplified example, which you can adapt to your needs. Let's say the C++ function takes an array of shorts with its size and looks like this:
void processBuffer(int16_t * buf, int count) {
...
}
We want to pass the contents of a Data from Swift as a buffer. Here is how one might go about doing that:
var myData = ...
myData.withUnsafeMutableBytes({(p: UnsafeMutablePointer<Int16>) -> Void in
processBuffer(p, Int32(myData.count / 2))
})
Please note that the buffer can be modified, not just read, in the C++ code, and the changes will be reflected in myData.
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
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.
i have an application which tracks body movement, it can also act like a server to send the body tracking data out via TCP.
My Client connects to the server and gets the data.
Before the data is send to a client something like this happens :
MTBF v10 = bodyPose2MTBF_v10(pose, m_startup, m_stream_position, 1);
ss << v10.get();
m_body_tracking_server->send(ss);
where the pose has all the information like position of the head as a vector, leg, shoulder position etc..SS is a new stringstream, and with v10.get() the stream is filled with the pose as a string. In the send method the stringstream(ss) is sent to the client.
In my client i get the stringstream. I also converted it back to mtbf. The problem is, the code is not from me, so i dont understand it all. When the pose is converted to mtbf something like this happens :
data.addFlag(0);
data << torso.x() << torso.y() << torso.z();
sensorConfig |= MTBFData_0_4::RightArmPosition;
data.addFlag(1);
.
.
.
I get that it is adding a "flag" so that i can recognize the torso for example, followed by the x y and z coordinates of the torso. but the add flag method looks like this :
addFlag(unsigned char n)
{
m_flag |= (1i64 << n);
m_buf.replace(7+8, 8, reinterpret_cast<char*>(&m_flag), 8);
return *this;
}
What exactly does this method?? shifting some stuff and reinterpret the char...i really need help to understand this!
thank you!
It's hard to say for sure without seeing more code but...
m_flag |= (1i64 << n); ... m_flag is probably an unsigned 64 bit int and this is ORing the nth bit of m_flag with 1.
m_buf.replace(7+8, 8, reinterpret_cast<char*>(&m_flag), 8); ... now that the flag has been modified, it replaces the current flag value in the buffer with the new flag value.
addFlag is designed to accumulate flags in the m_flag member (some kind of 64 bit integer). Each call updates a fixed, 8-byte field within m_buf with the latest m_flag value.
m_flag is able to accumulate several flags, each added with separate calls to addFlag.
Keep in mind that the flags in m_flags will accumulate, persisting until some other member function clears it.
Each flag value is associated with a single bit within a 64-bit integer value. This kind of program usually defines a list of possible flag values somewhere, either with a bunch of #define lines or as enums. Look for values between 0 and 63.
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.