TheImagingSource / ic4-examples

IC4 Example Programs
Apache License 2.0
5 stars 3 forks source link

How to display camera streams on WinForm? #23

Open Skullface9512 opened 2 weeks ago

Skullface9512 commented 2 weeks ago

I am developing a C# UI using IC4 camera. How can I display camera stream in real-time on the WinForm? Meanwhile, how to modify parameters such as resolution and exposure time for the camera and make it change in real-time? Is there any control that can be used?

TIS-Tim commented 2 weeks ago

For display, just put a ic4.WinForms.Display on your form, as shown in the Windows Forms example applications: https://github.com/TheImagingSource/ic4-examples/tree/master/dotnet/winforms/DialogApp-net6/DialogApp-net6

The example program also shows how to display the pre-built property dialog that allows the user to adjust settings.

Skullface9512 commented 2 weeks ago

Recently i'm working on putting the camera video stream into a UI WinForm and show a cross in image, the code i modified like that:

namespace CameraTest.Forms
{
    public partial class Calibration : Form
    {
        public Calibration()
        {
            InitializeComponent();
            ic4.Library.Init(apiLogLevel: ic4.LogLevel.Info, logTargets: ic4.LogTarget.WinDebug);
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            ic4.Grabber grabber = new ic4.Grabber();

            var selectedDeviceInfo = ic4.WinForms.Dialogs.ShowSelectDeviceDialog(this);
            if (selectedDeviceInfo == null)
                return;
            grabber.DeviceOpen(selectedDeviceInfo);
            var sink = new ic4.QueueSink(ic4.PixelFormat.BGR8, maxOutputBuffers: 1);
            sink.FramesQueued += (s, args) =>
            {
                // Get the new buffer from the sink
                // Buffer is disposed at the end of the using-block to allow re-queue
                using (var buffer = sink.PopOutputBuffer())
                {
                    // Create an OpenCVSharp view onto the buffer
                    // This view is only valid while the buffer itself exists,
                    // which is guaranteed by them both not being passed out of this function
                    var wrap = buffer.CreateOpenCvWrap();

                    int width = wrap.Width;
                    int height = wrap.Height;
                    //Console.WriteLine(width);
                    //Console.WriteLine(height);

                    OpenCvSharp.Point startPoint1 = new OpenCvSharp.Point(Convert.ToInt32(width / 2) - 500, Convert.ToInt32(height / 2));
                    OpenCvSharp.Point endPoint1 = new OpenCvSharp.Point(Convert.ToInt32(width / 2) + 500, Convert.ToInt32(height / 2)); 
                    OpenCvSharp.Point startPoint2 = new OpenCvSharp.Point(Convert.ToInt32(width / 2), Convert.ToInt32(height / 2) - 500);
                    OpenCvSharp.Point endPoint2 = new OpenCvSharp.Point(Convert.ToInt32(width / 2), Convert.ToInt32(height / 2) + 500);
                    Scalar color = new Scalar(0, 255, 0);
                    int thickness = 2;

                    Cv2.Line(wrap, startPoint1, endPoint1, color, thickness);
                    Cv2.Line(wrap, startPoint2, endPoint2, color, thickness);
                    display1.DisplayBuffer(buffer);
                }
            };

            // Start the stream
            grabber.StreamSetup(sink, display1,StreamSetupOption.AcquisitionStart);

            //grabber.StreamStop();
        }
    }
}

the running result is very strange, sometimes screen likely fix the first frame and don't change, sometimes it can show the video stream, but see no cross in image.

TIS-Tim commented 2 weeks ago

The display should not be used manually and as stream target at the same time.

This line manually displays the modified image:

display1.DisplayBuffer(buffer);

This line automatically displays all (original) images:

grabber.StreamSetup(sink, display1,StreamSetupOption.AcquisitionStart);

Don't pass the display to StreamSetup and the cross should be displayed correctly.

Skullface9512 commented 2 weeks ago

Ok, it works, and if i want to close this window through a button, how can i add this function.

TIS-Tim commented 2 weeks ago

"This Window"? You mean your Windows Form? Form.Close.

Skullface9512 commented 2 weeks ago

Just stop the video stream when click the button.

TIS-Tim commented 2 weeks ago

To stop the video stream, call grabber.StreamStop()

Skullface9512 commented 2 weeks ago

Where should I put this function in the above code and set relative button?

TIS-Tim commented 2 weeks ago

I am very sorry, but Windows Forms programming really is outside the scope of this forum.