Image weirdly changed after cv::resize() - c++

The related code is here(C++, opencv):
Rect rec = boundingRect(...);
image_grey.copyTo(gesture_grey, mask);
imshow("image_grey", gesture_grey(rec));
resize(gesture_grey(rec), gesture_grey, Size(256, 256));
imshow("gesture_grey", gesture_grey);
The result of imshow():
Why are the two images so different before and after resizing? How to fix it?

The problem is in copyTo method. It doesn't clear the content of 'gesture_grey' image container.
When you use gesture_grey(rec) you are effectively executing copy constructor, which gives you a new image container, so it's all cool. But when you call copyTo you are copying over to an existing target 'gesture_grey'.
To fix it, you need to re-initialize 'gesture_grey' in order to clear it, before calling copyTo. Otherwise, what you see is a combination of the previous content of 'gesture_grey' + new content you copy from image_grey.

Related

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

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?

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.

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();

How to Redraw/Repaint an IHTMLElement pointing to an image element in the DOM in IE9?

I've got a valid IHTMLElement object that points to an image in IE9. The image data was recently updated via an IDirectDrawSurface. I'm trying to find a way to force IE9 to repaint the image in the DOM after I update the image data. Could anyone please direct me to a method of forcing a repaint of an image that has been updated in this fasion?
Approaches I've tried:
HRESULT ret = pElement->get_style(&pStyle);
pStyle->put_visibility(L"hidden");
pStyle->put_visibility(L"visible");
// Or
pStyle->put_display(L"none");
pStyle->put_display(L"block");
Thanks for your time, and any tips would be greatly appreciated.
-Will
Have you tried resetting the src of the element? From what I can see, IE won't do anything if you set the same src that is already present, but looks like it can be tricked;
IHTMLImgElement pImg;
m_pElement->QueryInterface(IID_IHTMLImgElement, (void**)(&pImg));
_bstr_t bstrOriginalSrc;
pImg->get_src(bstrOriginalSrc.GetAddress());
pImg->put_src(L""); //Trick to avoid setting the same src as already present
pImg->put_src(bstrOriginalSrc);