Convert Mat to PvBuffer (from Pleora eBUS SDK lib.) - c++

thank you in advance for reading this.
For better readability I'll list pieces of info. necessary in point form.
building an app based on eBUS player sample provided by Pleora.
Grabbing images in 16 bit gray in 50 fps.
my app is processing image data using openCV within the OnBufferDisplay function in DisplayThread
so far, I have successfully processed images suiting my needs and am trying to convert my Mat(processed already) data back to PvImage or PvBuffer s.t. the image can be displayed in the eBUS Player using the already existing display function(this way I can still use other features in the Player app without having to make too many modifications to the original app).
The difficulty arises from the fact that display functions and other important functions are hidden in dlls. I can only make modifications to what's exposed.
The processing procedure is basically:
void Display Thread::OnBufferDisplay(PvBuffer *aBuffer){
aBuffer->Attach(imageMat.data, 614400);
//where imageMat is init'd as
//imageMat = cv::Mat(cv::Size(imgWidth, imgHeight), CV_16U);
//process.. the data....
//at this point, I Have my Mat object ready to go.
//supposed to create or have another PvImage or PvBuffer with the processed datahere for displaying.
//Display
mDisplay->Display(*aBuffer);
}
What I have tried so far is:
memcpy(aBuffer->GetDataPointer(), imageMat.data 614400);
//and
aBuffer->free();
//and/or
aBuffer->Detach();
//then
aBuffer->Alloc(614400); //since 640 * 480 in 16 bit gray
memcpy( Mat.data to buffer->datapointer);
Please help me clarify the following:
I have discovered after using Attach(), the passed aBuffer does no longer properly display image. Does that mean this function not just copies the data from aBuffer to imageMat.data but erases the data in aBuffer and then copies it to imageMat.data?
I went for Attach() because memcpy(imageMat.data, aBuffer->GetDataPinter(), size); didn't work. It didn't copy the data properly like the way Attach() does. Anybody know why?
The description for Attach() provided by Pleora is "Attach this PvBuffer to an external memory buffer. To use an internal memory buffer, use Alloc.".
In summary,
How do you properly create a PvImage or a PvBuffer object that contains the data from my Mat object in order to pass to the Display() function?
Are there any detours to make this work without having to create such objects?

Related

How to create std::map of Gdk::Pixbuf instances and use it in Gdk::Cairo

I guess one may found it trivial, but I ask it here since I could not find a straightforward answer.
Let's dive into the problem:
Having a resource of multiple images along with cairo context that is using these images incessantly. Naturally, I can do so as below:
Glib::RefPtr<Gdk::Pixbuf> image;
image = Gdk::Pixbuf::create_from_resource("/image/icon1"); //there are numerous icons out there
Then I can use it with Cairo context pointer like this:
bool MyClass::on_draw(const Cairo::RefPtr<Cairo::Context> &cr)
{
// ... some code
Gdk::Cairo::set_source_pixbuf(cr, image, x0 , y0); //x0 , y0 : somewhere in the context
cr->paint();
return true;
}
Images are not changing but it creates Pixbuf instance everytime. I want to use c++ map and put my icons in it. Then, I want to get the image pointer from the map. I did something like this:
std::map<Glib::ustring , GdkPixbuf*> map_Images;
// ..
map_images.insert(pair<Glib::ustring , GdkPixbuf* >("icon1" , image->gobj() )); // I do the same with all of my frequently referred icons
Now, I don't know how should I call this map to use with Cairo context. In other words, how should I make a Glib::RefPtr from the base object, say GdkPixbuf*
I would recommend you to make map_Images a map of type std::map<Glib::ustring , Glib::RefPtr<Gdk::Pixbuf> > and make it data member of MyClass. Because Glib::RefPtr will deallocate the owning object once all references are lost to that pointer.
What I want to say is that if you have code similar to this:
... some function, say fun1
{
Glib::RefPtr<Gdk::Pixbuf> image;
image = Gdk::Pixbuf::create_from_resource("/image/icon1");
map_images.insert(pair<Glib::ustring , GdkPixbuf* >("icon1" , image->gobj() ));
} // image object will die here. So, Gdk::Pixbuf held by Glib::RefPtr will be deallocated
Now, If you will try to access Gdk::Pixbuf * from the map, you will get dangling pointer.
If that is the case, skip the part that follows. Otherwise, continue reading.
Creating Glib::RefPtr of type Gdk::Pixbuf seems to be simple. As per source code that I found on GitHub: https://github.com/GNOME/glibmm/blob/master/glib/glibmm/refptr.h, make_refptr_for_instance(T_CppObject* object) API should do the job for you.
If you really want to create Glib::RefPtr of type Gdk::Pixbuf, you may get it by calling:
Glib::RefPtr<Gdk::Pixbuf> imageForIcon1 = make_refptr_for_instance<Gdk::Pixbuf>(map_images["icon1"]); // assumption: map_images already has an element with key "icon1"
Hope it helps.

QChart realtime performance

I am using QChart for an application. The application need to show some data realtime. There will be one chart and 24 series in the chart. The data rate is 400pts for every channel.
I used another thread for receiving and processing received data and emit the processed data to a slot for append datas to update the chart series.
I refered to https://doc.qt.io/qt-5/qtcharts-audio-example.html. In my case, each series is limited to 2000 points, if the number of points in the series is less than 2000, add the new point to the series, if the number of points in the seried is more than 2000, delete first point, move the rest of datas to left and add the new point in the end. This will make the chart look like move from right to left.
For good performance, I also used series->replace() and series->setUseOpenGL(true).
My problem is that the application will get freezed soon when it started. I tried delete the codes of update the chart, everything looked fine. Could anyone help me how to improve the performance of update the chart?
Thanks!
I have the same problem. The main problem I think is, that QLineSeries sends the signal pointAdded() and triggers a repaint. Additionally append() and remove are performance sinks. QtChart does only support QList and no form of a ring buffer as far as I know.
I tried the way putting new data into a QQueue<QPointsF> and copy the data within a timer hanler set to 20 Hz. To avoid updating I disable these:
void
MyGraph::handle_timer_timeout()
{
_chartView->setUpdatesEnabled(false);
// _chart->removeSeries(_series);
while(_buf->count()>0){
_series->append(_buf->dequeue());
_series->remove(0);
}
// _chart->addSeries(_series);
_axisX->setRange( _series->at(0).x(),
_series->at(_seriesSize-1).x());
_axisY->setRange(-1,1);
_chartView->setUpdatesEnabled(true);
}
This results in roughly 20-30% less processor usage.
I also found the hint that temporary removing the series (removeSeries(),addseries()) can result in some improvements but I can't confirm that.
This may be better but not really good enough. I hope someone finds a better solution.
or use QLineSeries::replace(). For that I use a double buffer QVector<QVector<QPointF>> *_lists:
void
MyGraph::handle_timer_timeout()
{
_chartView->setUpdatesEnabled(false);
auto listsother = (_listsCrurrent+1)%2;
auto bufcnt = _buf->count();
//
QVector<QPointF> *newData = &_lists->data()[listsother];
int idx;
for(idx=0; idx<_seriesSize-bufcnt;idx++){
newData->replace(
idx,
_lists->at(_listsCrurrent).at(idx+bufcnt));
}
for(; idx<_seriesSize;idx++){
newData->replace(
idx,
_buf->dequeue());
}
_listsCrurrent = listsother;
_series->replace(_lists->at(_listsCrurrent));
_axisX->setRange( _series->at(0).x(),
_series->at(_seriesSize-1).x());
_axisY->setRange(-1,1);
_chartView->setUpdatesEnabled(true);
}
This is more performant on my computer.
Alternatively you can take a look on QWT.

In Qt why cacheKey differs for same icon

Take a form
Place two CommandLinkButton(s) on the form
Place a PushButton on the form
Right click PushButton-> Go to slot...
Choose clicked()
Write following code:
std::cout << ui->commandLinkButton->icon().cacheKey() << std::endl;
std::cout << ui->commandLinkButton_2->icon().cacheKey() << std::endl;
Why does that code print two different values for the cachekey?
We did not change the icon of any CommandLinkButton so both have the same default icon!
My problem is like this:
I have a push button with an icon on it, which is coming from resources.
I want to verify in test code that it has the same required icon on it.
To do that I compare the cachekey of image on the push button and cachekey of QPixmap object having same image like this:
const QPixmap image(":/MyProject/Images/Yellow_Icon_40x40.png");
if(image.cacheKey() == ui->PushButton->icon().cacheKey())
{
cout<<"OK";
}
But that test fails because cacheKey turns out to be different.
So what is the best way to do that check?
Basically like calculating hash of image and match that hash, which should always be same for any instance of same image.
That's because two icons are not cached in the same cache and/or not copied from the same object. Look at item 2 of this answer and cacheKey documentation.
To get the same cacheKey for different icons you should create an icon object in constructor of your window and call setIcon on it for both CommandLinkButtons.
Update:
To compare the icon with a bitmap from file by hash, you need some data-based hashing. Fortunately, Qt provides a bunch of qHash functions and qHashBits function for continuous memory blocks. You may compare your images hashes like this:
// assume image and icon object are declared as in your question
QImage imImage = image.toImage();
QImage imIcon = ui->PushButton->icon().pixmap(QSize(1024,1024)).toImage();
auto hbImage = qHashBits(imImage.constBits(), imImage.byteCount());
auto hbIcon = qHashBits(imIcon.constBits(), imIcon.byteCount());
if(hbImage == hbIcon) {.......}
Here we get image raw data in a very clumsy and unnatural way and then compute hashes of it. It's probably not what you want. Hashes returned by qHashBits are not the values returned by cacheKey. Furthermore, these hashes may differ as image is loaded directly from file, while QIcon may perform some processing on it's image during construction. qHashBits comes from Qt's hash table implementation, so it implies that minor changes of input data yield significant changes of returned hash. To compensate possible difference, you may construct QIcon object from image with options same as in the interface, and then obtain icon's data.
And it's not clear from your example, what for to take hashes before comparison? Hashing requires whole data traversal, so it will not be faster that just std::equals on data until you compare thousands of images to one image.

Windows Forms - picture box. How to delete an Image

I am working in an application where there is a conbobox and a picturebox. The user selects a path and the conbobox loads paths to 2000 images, and displays the first one. When the user changes the index of the conbobox the image displayed changes, but I don't know how to delete the image in the picturebox.
If I just overwrite the image it doesnt do the job, as when I do it repeatedly the program crashes because of memory. How do I delete a image Inside the picturebox?
EDIT:
I made few changes and can't seem to reproduce the error again.. so maybe it was something else. but just for checking, is this code leaking memory?
tips: config is a singleton containing where some info, in this case, where the images are.
private: System::Void comboBox_image1_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e) {
System::String^ aux;
DIC_config* config=DIC_config::Instance();
if(config->images_path!=NULL){
aux=gcnew System::String(config->images_path);
aux=aux+"\\CAM_0\\Snap_0_0"+(this->comboBox_image1->SelectedIndex+1)+".bmp";
System::IO::FileStream^ image_file=gcnew System::IO::FileStream(aux,System::IO::FileMode::Open,System::IO::FileAccess::Read);
System::Drawing::Bitmap^ img = gcnew System::Drawing::Bitmap(image_file);
this->pictureBox_image1->Image=img;
//img->~Bitmap(); this doesnt work, deletes the image of picturebox and makes the program chrash
}
}
You have to dispose the old image. Forgetting to do so makes it likely your program runs out of unmanaged memory when the garbage collector doesn't run frequently enough. Bitmap objects are quite small, you can allocate thousands of them without ever triggering a GC, but can consume a lot of unmanaged memory for the pixel data. You dispose objects in C++/CLI with the delete operator, it calls IDisposable::Dispose().
Do note that the FileStream you use is also a disposable object. Doing it this way requires you to keep the stream opened while the bitmap is in use and close it afterwards. You correctly did not dispose the stream but forgot closing it. Too hard to get right, it is much easier to use the Bitmap constructor that accepts a string for the file path so the Bitmap class manages the underlying stream itself. Fix:
aux = config->images_path;
aux += ....;
System::Drawing::Bitmap^ img = gcnew System::Drawing::Bitmap(aux);
delete this->pictureBox_image1->Image;
this->pictureBox_image1->Image = img;
This doesn't work because you are trying to call destructor of the class, not the instance. Furthermore you do not need to call it as System::Drawing::Bitmap is under control of garbage collector, so the finalizer ( !Bitmap() ) will be called automatically if it's not referenced any longer.
What you can do if you want to close it in picturebox is
delete this->pictureBox_image1->Image;
image_file->Close(); //after closing/deleting the open bitmap
btw. your code is not pure c++, but c++/cli, so I've added the tag
First set a null pointer to the Image property and refresh the pictureBox, as given below,
pictureBox_image1->Image = nullptr;
pictureBox_image1->Refresh();

Updating itk image in Qt user interface

I have a problem that I would like to tell you because is about some days that I don’t have new ideas.
I have an image pointed with a double* pointer, and I want to translate it into itk::smartpointer for updating the user graphic interface, for this purpose I made this method :
void prueba_r01::double2itk( double *im_proc, ImageType::Pointer *salida, int alto, int ancho)
// This method translate the double* image into itk:smartpointer image
ImageType::IndexType pixelIndex; // pixelIndex[0]= index x-axis; pixelIndex[1] = index y-axisy
ImageType::PixelType pixelValue;
ImageType::PixelType aux; //auxiliar variable for checking the behaviour of the programm
// Doing a sweep of all the image (is in double *im_proc) translating the values into itk pointer format
for (int x=0; x<ancho; x++){ // ancho: widht of the image
pixelIndex[0]=x;//x position
for (int y=0; y<alto; y++){ // alto: height of the image
pixelIndex[1]=y;//y position
pixelValue= *(im_proc+x+ancho*y);
(*salida)->SetPixel(pixelIndex,pixelValue);
aux = (*salida)->GetPixel(pixelIndex); // checking that the image has been correctly transtaled from im_proc to salida-- > CHECKED
}
}
}
And then is called here:
//Translation of the double* image into itk:smartpointer image
double2itk(out_inv, &(ui.imageframe->imagereader), alto, ancho);
And after that, the user interface is updated:
// Update of the image shonw in the user interface
ui.imageframe->update();
The problem is that it seems that everything is working correctly, but the image in the interface is not updated.
Another option also valid for my project could be to stored the image in a ‘.bmp’ or ‘.jpeg’ file.
Could someone help me? Any ideas of what is not working properly? Is there any function for creating this image files?
ITK has built-in mechanisms for this, with some considerable safety advantages. Also: they can be used in a pipeline like any image source, and because they use your existing array they will be considerably faster (I think) than looping over the indices.
http://www.itk.org/Doxygen/html/classitk_1_1ImportImageFilter.html
http://www.itk.org/Doxygen/html/classitk_1_1ImportImageContainer.html
http://www.itk.org/Wiki/ITK/Examples/IO/ImportImageFilter
You must use the ImportImageContainer, and be very careful how you set the memory management options.
By default ITK will clean up after itself, and will expect to be able to delete the memory pointed to by your external pointer.
There are examples of this in the Users Guide.
There is also a very nice wiki example at: http://www.vtk.org/Wiki/ITK/Examples/IO/ImportImageFilter