secile / UsbCamera

C# source code for using usb camera and web camera in WinForms/WPF. With only single CSharp source code. No external library required.
MIT License
179 stars 55 forks source link

Can't able to set brightness and exposure at run time when camera running on different thread #32

Closed rajeshamudala closed 2 months ago

rajeshamudala commented 7 months ago

Hello,

I am currently working on a project involving two cameras. Initially, I was able to adjust exposure, brightness, and contrast during camera creation. However, when attempting to modify brightness or contrast dynamically at runtime using sliders or other methods, I encountered an exception, as shown in the attached screenshot. Interestingly, when I ran the cameras on the main thread, adjustments to brightness and contrast worked fine. However, my requirement is to run each camera on a separate thread. How can I ensure that I can adjust brightness and contrast when the cameras are running on different threads?

here is code to adjust brightness ` public void SetExposure(int val) { try { UsbCamera.PropertyItems.Property prop; prop = Camera_Device.Properties[DirectShow.CameraControlProperty.Exposure]; if (prop.Available) { if (val > prop.Max) { val = prop.Max; } else if (val < prop.Min) { val = prop.Min; } prop.SetValue(DirectShow.CameraControlFlags.Manual, val); } else { Console.WriteLine("Exposure is not there for camera :"); } }catch(Exception ex) { Console.WriteLine("Exposure is not changing due to :" + ex.Message); }

    }

` Screenshot (93)

secile commented 7 months ago

Hello, thank you for your question. As you said, it is true that it happens exception if you access camera instance from different thread that create camera instance.

To handle this situation, you have to access camera instance same thread that create camera instance. To do this, I think it's depend on your program architecture, there are some solutions, use Task, ReactiveExtentions, or switch thread by using event Set() and WaitOne().

Here is sample.

private void Form1_Load(object sender, EventArgs e)
{
    System.Threading.ThreadPool.QueueUserWorkItem(x =>
    {
        // here is worker thread. create camera instance here.
        UsbCamera camera = CreateCamera();

        var value_changed_event = new System.Threading.AutoResetEvent(false);
        int value = 0;
        numericUpDown1.ValueChanged += (s, ev) =>
        {
            // here is UI thread. to access camera instance, use event.Set().
            value = (int)numericUpDown1.Value;
            value_changed_event.Set();
        };

        // main loop.
        while (true)
        {
            // wait until value changed.
            value_changed_event.WaitOne();
            // resume thread if event.Set() invoked.

            // set property.
            var prop = camera.Properties[DirectShow.CameraControlProperty.Focus];
            if (prop.Available)
            {
                prop.SetValue(DirectShow.CameraControlFlags.Manual, value);
            }
        }
    });
}
rajeshamudala commented 2 months ago

Thank you it's worked for me!!!