Ask Your Question
0

How to implement the imshowCompare() function without memory leak?

asked 2017-03-27 03:07:04 -0600

updated 2017-04-09 07:25:57 -0600

I implemented the imshowCompare() function that switch the output and the original image by the left mouse button click in cv::imshow windows. This is a very useful function for testing. The code is as follows, but can not solve the problem of memory leak.

   void on_MouseHandle_Compare(int event, int x, int y, int flags, void* param);

   typedef struct {
    String winname;
    Mat src;
    Mat dst;
} strImshowCompare;

void imshowCompare(const String& winname, const Mat& src, const Mat& dst)
{
    // src, dst must be cloned, otherwise the external Mat may be modified.
    Mat newsrc = src.clone(); // Their memory will leak.
    Mat newdst = dst.clone(); // Their memory will leak.
    cv::imshow( winname, newdst);

   // struct strImshowCompare can't delete in this function! It must delete after the window is closed. But I don't know when the window is closed.
    strImshowCompare* str = new strImshowCompare; 
    str->winname = winname;
    str->src = newsrc;
    str->dst = newdst;

    cv::setMouseCallback(winname, on_MouseHandle_Compare, (void *)str);
}

void on_MouseHandle_Compare(int event, int x, int y, int flags, void* param)
{
    strImshowCompare* str = (strImshowCompare*) param;

    switch (event) {
        case cv::EVENT_LBUTTONDOWN: { 
            cv::imshow(str->winname, str->src);
            break;
        }
        case cv::EVENT_LBUTTONUP: {
            cv::imshow(str->winname,  str->dst);
            break;
        }
    }
}
edit retag flag offensive close merge delete

Comments

I don't know for the memory leak but at least you should be able to do something like that:

  strImshowCompare *ptr = new strImshowCompare;
  imshowCompare("Test", img1, img2, ptr);
  while (true) {
    int c = waitKey(30);
    if (c == 27)
      break;
  }

  delete ptr;
Eduardo gravatar imageEduardo ( 2017-03-27 10:31:01 -0600 )edit

Yes, we can pass the pointer, and then manually release it. The bad thing is that it's easy to forget to release. Change raw pointer to smart pointer may solve this problem. But pass a pointer was also verbosely. Hope to have the simple calling way like imshowCompare("winname", src, dst).

logic1988 gravatar imagelogic1988 ( 2017-03-28 00:25:04 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2017-04-09 09:45:22 -0600

berak gravatar image

updated 2017-04-09 09:46:52 -0600

actually, your userdata has to stay valid, until destroyWindow() is called. clicking the close button will not remove the internal window management structure, the next call to imshow() with the resp. name will just reopen it, so , careful with that axe..

either favour @Eduardo's solution (keep it alive until the end) or simply reverse the logic. maybe you do not need that struct at all ? rather move the processing into the mainloop:

void on_mouse(int event, int x, int y, int flags, void* param)
{
    int *clicked = (int*)param;
    *clicked = even; // just pass it on
}

int main() {
  int clicked = 0; // mouse state
  String winname = "Test";
  namedWindow(winname);
  setMouseCallback(winname, on_mouse, (void *)(&clicked));
  while (true) {
    Mat src, dst = ... // your processing

    if (clicked == 1) // LBUTTON
       imshow(winname, src);
    if (clicked == 2) // RBUTTON
       imshow(winname, dst);

    int c = waitKey(30);
    if (c == 27)
      break;
  }
edit flag offensive delete link more

Comments

Thank you very much, but imshowCompare function will be used frequently, this is too cumbersome.

logic1988 gravatar imagelogic1988 ( 2017-04-10 07:26:14 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-03-27 03:07:04 -0600

Seen: 217 times

Last updated: Apr 09 '17