2

I am new to C++ gui design and I am not too familiar with using pointers. Recently I have run into a few problems when trying to get an OpenCV Mat Image to display in a PictureBox in a constructed gui. I have searching online and even found a very similar post to my question but when trying to implement the guidance I ran into an exception when trying to operate the gui.

A very similar post Displaying webcam feed in cv::Mat format in a picturebox

Code I grabbed from this post to save you a click:

void DrawCVImage(System::Windows::Forms::Control^ control, cv::Mat& colorImage)
{
    System::Drawing::Graphics^ graphics = control->CreateGraphics();
    System::IntPtr ptr(colorImage.ptr());
    System::Drawing::Bitmap^ b  = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);
    System::Drawing::RectangleF rect(0,0,control->Width,control->Height);
    graphics->DrawImage(b,rect);
    delete graphics;
}

Now I am trying to display a "video" feed (really an array of cv::Mat Objects) but I am having a "Source Not Available"/System.ArgumentException: 'Parameter is not valid.' screen come up when I attempt to call the function that houses that playback. I also know specific line of code that throws the issue is the line

System::Drawing::Bitmap^ b  = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);

Now for specifics, the form has an event (currently the click on the picture box, but I want to move to a "play" button in the future) and on this event, the code:

private: System::Void leftEyeImage_Click(System::Object^ sender, System::EventArgs^ e) {
    std::cout << "Click Received" << std::endl;
    cv::Mat& frame = cv::imread("Desktop/testcapture.png");
    std::cout << "Import successful" << std::endl; 
    drawLeftEye(this, frame);
}

This code does get execute on click and starts the function drawLeftEye. The function is a modified version of the code from the other post and is below:

This is on the ShowResults.cpp file

namespace DevProject {
    void ShowResults::drawLeftEye(System::Windows::Forms::Control^ control, cv::Mat& framebmp) {
        System::Drawing::Graphics^ graphics = control->CreateGraphics();
        std::cout << "Now Here" << std::endl;
        System::IntPtr ptr(framebmp.data);  

        // Issue line 
        System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(framebmp.cols, framebmp.rows, framebmp.step, System::Drawing::Imaging::PixelFormat::Format32bppRgb, ptr);

        std::cout << "Converted successfully" << std::endl;

        System::Drawing::RectangleF rect(0, 0, control->Width, control->Height);        //No issue
        graphics->DrawImage(b, rect);                                   
        std::cout << "Now Here before delete" << std::endl;
        delete graphics;
        //delete b;
    }
}

I know based on my cout statements that I do make it into my function and I know my code compiles and runs through the function if I comment out the line:

System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(framebmp.cols, framebmp.rows, framebmp.step, System::Drawing::Imaging::PixelFormat::Format32bppRgb, ptr);

//As well as (but only because b is defined in the line above^
graphics->DrawImage(b, rect); 

I am not quite sure how to fix this, my friend mentioned this could be a memory issue but I don't know how I would go about fixing it. It is also very possible I have made a simple mistake in the design of this or where my pointers are going and I am just not competent enough to know the error.

By the way the pointer for "this" that is called in the function is linked to the Windows Autogenerated code (from gui construction) of:

this->leftEyeImage->Anchor = System::Windows::Forms::AnchorStyles::None;
this->leftEyeImage->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;
this->leftEyeImage->Location = System::Drawing::Point(11, 836);
this->leftEyeImage->Name = L"leftEyeImage";
this->leftEyeImage->Size = System::Drawing::Size(991, 646);
this->leftEyeImage->TabIndex = 4;
this->leftEyeImage->TabStop = false;
this->leftEyeImage->Click += gcnew System::EventHandler(this, &ShowResults::leftEyeImage_Click);

Any and all advice or tests would be very appreciated as I am both interested in the answer and the reasoning. Thanks in advance!

William Miller
  • 9,839
  • 3
  • 25
  • 46
TheGovinor
  • 21
  • 2
  • Hello, I'm facing a similar issue when displaying Mat in a picture box. Can you please share the solution if you have found any. Thanks! – Shan Apr 26 '20 at 17:03
  • Does this answer your question? [Why must "stride" in the System.Drawing.Bitmap constructor be a multiple of 4?](https://stackoverflow.com/questions/2185944/why-must-stride-in-the-system-drawing-bitmap-constructor-be-a-multiple-of-4) – Lev Leontev Dec 26 '20 at 12:42

0 Answers0