What is the correct way of creating a small list of cv::Mat and iterating over it? - c++

I am new to C++ and I am trying to create a list of cv::Mat.
This could allocate quite a lot of memory, but I only have around ten small Mat's to load in the list.
I made this code, but not sure why it is not working.
void Utils::getFramesFromVideo(std::string file,std::list<cv::Mat>& listMatOutput) {
cv::VideoCapture* videoCapture = new cv::VideoCapture(file);
bool hasImage = false;
cvNamedWindow("WhileReading", 1);
do {
cv::Mat frame;
hasImage = videoCapture->read(frame);
if (hasImage) {
listMatOutput.push_back(frame);
imshow("WhileReading", frame);
waitKey(0);//give some time to see the frame (debug)
}
} while (hasImage);
cvNamedWindow("AfterReading", 2);
for (std::list<Mat>::const_iterator iterator = listMatOutput.begin();
iterator != listMatOutput.end(); iterator++) {
imshow("AfterReading", *iterator);
waitKey(0);//give some time to see the frame (debug)
}
videoCapture->release();
}
The first loading is displaying the frames correctly, but in the second window (AfterReading) the image is black with red stripes.
Could someone please give some advice?

The list format is an STL container, meaning that you've got some things to keep in mind to work with it. push_back() is the preferred method of adding instances to the container, much like using an iterator is the preferred method of accessing the elements of the list. If you try to directly set an element of the list to a cv::Mat() you're working on, then a) you need to know exactly what sort of wrapping the list is doing to each instance, so you can do it properly yourself, and b) you're defeating the purpose of using an STL container in the first place, which is to abstract away the details of the list.
You don't necessarily need to use the frame.clone() call in your code, as this creates a deep copy of the image and takes up precious resources. I know that I've used std::vector<cv::Mat> in the past without having to make deep copies for each element in the vector, so I assume that you should be able to pass the Mat itself to a list. Consult the C++ documentation on STL lists.
Another thing you might consider, if low memory usage and speed of access through the list is a concern, and your number of images is low, is a list of image pointers. Keep your images stored as individual cv::Mat instances, and make your list of type std::list<cv::Mat*>, passing the handle of the image to the push_back() call. Of course, with this method, your images will not be 'thread safe' because they will be stored in one place, but called and worked on from another. I hope this shed a little light on your inquiry.

I tried all sort of things, like changing to pointers or vectors and checking for code optimizations on GCC. Then after trying to clone cv::Mat it worked:
listMatOutput.push_back(frame.clone());
Would be glad if anyone could tell me why and suggest a better way of doing, so I can choose a better answer then my own.

Related

Efficiently iterating large amounts of data

Introduction
First of, I must say this is being done for an online game server, which keeps track of every object in a map, be it a player or an AI (NPC or however you want to call it).
It must not only keep track of them, but notify among the players their near players. I've solved this, and I'm currently using a multi-threaded approach, which perfectly works.
My problem
I'm storing all that objects in an hash table. We could consider that hash table to be an unordered_map, though I'm in fact using the rde::hash_map, as it is faster on inserting and fetching (self tested), though takes more RAM (not an issue now).
The thing is, that map stores a unique ID for the object (64 bits), plus the object pointer, something like:
rde::hash_map<UInt64, Object*>
My problem is:
My application (a server) must run in a loop (inside a thread) which must be called every ~50ms, as to keep things runing smooth. The loop code looks as follows:
void loop()
{
UInt32 prev = clock();
UInt32 prevSleep = 0;
while (1)
{
UInt32 diff = clock() - prev;
prev = clock();
maps.update() // Suppose map is a class, which stores the objects map
if (diff <= 50 + prevSleep)
{
prevSleep = 50 + prevSleep - diff;
sleep(prevSleep);
}
else
prevSleep = 0;
}
}
And now, to the point, the function map::update() which is the one causing the loop increasing to values of 4500ms.
Each time an update is called, the map object must check for new object being added to the store, if an object is added, that object must notify all the other objects of it being added, which I do by (pseudocode):
foreach obectsToBeAdded as joiner:
foreach objectsList as object:
joiner->notify(object);
object->notify(joiner);
Later on, an internal update of each object must be called, I do it by (pseudocode again):
foreach objectsList as object:
object->update();
And, if that was not enough, the above loop must be expanded to:
foreach objectsList as object:
object->update()
// Visit all the other objects
// Called once every 1 sec for the object, not on every call
foreach objectsList as other:
if other != object:
object->visit(other)
My attemp to optimize this
Merge the first loop (adding and notifying) with the update loop, as it follows:
foreach objectsList as object:
foreach objectsToBeAdded as joiner:
object->notify(joiner)
joiner->notify(object)
object->update()
// Called once every 1 sec for the object, not on every call
foreach objectsList as other:
if other != object
object->visit(other)
This works while the objects count is not big, as soon as it increases the loops start to take up to 4 seconds, which goes far beyond to the 50ms I'm looking for.
My question
Is there any other way of optimizing this even more? I've though about using octrees to keep track of the objects positions in the map, but then came to the conclusion that it would only worsen the problem.
I've also divided each map to 35 units (35 is the "view range", LOS) of an entity, so that a given rde::hash_map only contains units which are to be seen by each other, thus that need updates. Works as long as objects count is low...
What else could I do? Thank you!
Note
All those foreach are loops using iterators, like rde::hash_map<...>::iterator from objects.begin() to objects.end()
Other optimitzations, such as not updating if there's is no player (a real user, and not a NPC), freeing memory when no player is on a given map, and such, are already being taken into account.
The first optimization that comes to mind besides spatial segmentation so objects are only informed about changes near them (such as with a quadtree) is: Does EVERY object have to be informed about EVERY change? Why not tell each object, 'Every frame, I'll run your update method. In your update method you can look for everything you want to (for example, there might be a buffer of all changes that occurred this frame/in recent frames) and update yourself as you please'. This way you don't spend CPU cycles notifying objects about things they don't actually need to know or care about.
Also, have you run a CPU profiler on your program, and verified that the hot spots (where the most CPU time is being spent) are where you think they are?
See comments for further discussion:
|
|
\|/
V

Vector_push back not populating the vector (c++)

I'm not getting any error messages, simply my vector is not populating. Looking at the vector in the watch list, nothing is being copied. Why is this?
I've tried two ways.
The first
std::vector<Point3D*> hitpoints;
local_hit_point = sr.local_hit_point; //local_hit_point class Point3D
hitpoints.push_back(local_hit_point);
The second way I tried to use pointers
std::vector<Point3D*> hitpoints;
Point3D* hittingpoint_ptr = new Point3D;
local_hit_point = sr.local_hit_point;
hittingpoint_ptr = &local_hit_point;
hitpoints.push_back(hittingpoint_ptr);
I got vectors in other places in my code which work. Am I really just being daft, but I can't seem to figure out why its not working.
My best guess is that you have an issue with you debugger..
First Suggestion;
Clear everything in your watchlist because they can change the behaviour of the execution
check it again..
Second suggestion;
Create a new project and write a simple code like the one above and see whether your vector is populating..If this simple project works, you should provide us more code and details..
simply my vector is not populating.
It is populating. However
Looking at the vector in the watch list ...
I used hitpoint.size()
Results of function/method calls (size() is a method) are not automatically updated in visual studio watch list (because you haven't told what os/compiler you use I had to assume it is visual studio). I.e. if you enter function call into watch list, it'll calculate results, but will not call function again until you manually refresh it. Instead of function call, add vector itself into watch list.

ID3DX10Mesh::CloneMesh

I'm trying to copy mesh in DirectX10. I wrote this:
HR(mesh->CloneMesh(mesh->GetFlags(),data.GetPosSemantic(),data.GetInputElementDesc(),
data.GetDescCount(),&mMesh));
but when i try to render the mesh nothing appers on the screen.
when i write
mMesh = mesh;
There are no problems with the rendering(unless when I release "mesh" ).
Thanks in advance.
If you want to duplicate the mesh without any changes, you should use the second approach and call then mMesh->AddRef() to declare the data is owned by two pointers (better idea is to use some kind of smart pointers - COM or boost::shared_ptr adapted to COM-like objects).
But the first case should work too - what is the data object about?

Boost GIL image constructors

I'm currently trying to figure out how to use the Generic Image Library included in Boost. Right now, I just want to use the library to store pixel data and use the Image IO to write PNGs. I'm having trouble understanding just how to set up the object however.
The hpp says
image(const point_t& dimensions,
std::size_t alignment=1) : _memory(0), _align(alignment) {
allocate_and_default_construct(dimensions);
}
but I cannot find any references to point_t except a type_def for view_t::point_t to point_t.
Also, the tutorial found with the GIL seems to only include writing filters and generic algorithms, and thus each function example they provide has a source image view, from which they take the dimensions.
Am I going about this the wrong way? Or is there something I've missed completely?
Thanks in advance
Edit: I don't know if anyone cares, or has read this, but for the record, I just used the boost interleaved image function to create a PNG. It's not exactly the same solution, but it works for my applications.
it sounds like you solved your problem in the meantime, but just for the record... here are some pointers to information about your problem:
First of all you may have missed the second constructor of boost::gil::image, which offers explicit access to the horizontal and vertical dimensions without the need of the point_t:
image(x_coord_t width, y_coord_t height,
std::size_t alignment=0,
const Alloc alloc_in = Alloc()) : _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
allocate_and_default_construct(point_t(width,height));
}
point_t will most likely refer to the point2 class template defined in boost/gil/utilities.hpp.
In general you should check the complete documentation of Boost GIL for all questions not mentioned in the tutorial. For a deeper understanding of the library it is absolutely necessary to get familiar with the Design Guide and the Doxygen Documentation.

c++ use new to Image gdi+

im using gdi+ to output my images.
i tried to use the keyword new but it didn't work.
shot(L"image name") = new Image;
that didn't work any other ideas how to make it work
Something like this seems a lot more likely:
Image *image_object = new Image(L"Image Name");
Except that there's a pretty decent chance you don't want to allocate the Image object dynamically at all -- unless you really do, you generally want to just define an object with automatic storage duration:
Image image_object(L"Image Name");
The GDI+ Image class is not default constructible. You have to supply some parameters to the constructor in order to create one - see here.
You may well be better off using Gdiplus::Bitmap, which derives from Image. That seems more likely if you're trying to output it.