简体   繁体   English

调整摄像头亮度(曝光/增益)C#

[英]Adjust webcam brightness (exposure/gain) C#

I'm trying to adjust the brightness of my webcam. 我正在尝试调整网络摄像头的亮度。 I need 3 diffrent pictures taken with a diffrent brightness setting. 我需要使用不同的亮度设置拍摄3张不同的照片。 I don't want to make it manual so if want to include the settings in the programm. 我不想手动设置,因此如果要在程序中包括设置。

Below ist the code I'm using. 下面ist我正在使用的代码。 With the methode GetFrame() a get the next picture from the webcam. 使用方法GetFrame()可以从网络摄像头获取下一张图片。 I know there is DirectShow (iamvideoprocamp), and I Read the other questions but I still don't know how to integrate it. 我知道有DirectShow(iamvideoprocamp),我读了其他问题,但我仍然不知道如何集成它。 Can someone give me a hint or an example in c#. 有人可以在C#中给我一个提示或示例吗? Thanks. 谢谢。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using DirectShowLib;

namespace Kugel
{
    class Frames
    {
        // property variables
        private int m_Width = 640;
        private int m_Height = 480;
        private int mCapHwnd;

        // global variables to make the video capture go faster
        private IDataObject tempObj;
        private System.Drawing.Image tempImg;


        #region API Declarations

        [DllImport("user32", EntryPoint = "SendMessage")]
        public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);

        [DllImport("avicap32.dll", EntryPoint = "capCreateCaptureWindowA")]
        public static extern int capCreateCaptureWindowA(string lpszWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, int hwndParent, int nID);

        [DllImport("user32", EntryPoint = "OpenClipboard")]
        public static extern int OpenClipboard(int hWnd);

        [DllImport("user32", EntryPoint = "EmptyClipboard")]
        public static extern int EmptyClipboard();

        [DllImport("user32", EntryPoint = "CloseClipboard")]
        public static extern int CloseClipboard();

        #endregion

        #region API Constants

        public const int WM_USER = 1024;

        public const int WM_CAP_CONNECT = 1034;
        public const int WM_CAP_DISCONNECT = 1035;
        public const int WM_CAP_GET_FRAME = 1084;
        public const int WM_CAP_COPY = 1054;

        public const int WM_CAP_START = WM_USER;

        public const int WM_CAP_DLG_VIDEOFORMAT = WM_CAP_START + 41;
        public const int WM_CAP_DLG_VIDEOSOURCE = WM_CAP_START + 42;
        public const int WM_CAP_DLG_VIDEODISPLAY = WM_CAP_START + 43;
        public const int WM_CAP_GET_VIDEOFORMAT = WM_CAP_START + 44;
        public const int WM_CAP_SET_VIDEOFORMAT = WM_CAP_START + 45;
        public const int WM_CAP_DLG_VIDEOCOMPRESSION = WM_CAP_START + 46;
        public const int WM_CAP_SET_PREVIEW = WM_CAP_START + 50;

        #endregion

        #region Start and Stop Capture Functions

        /// <summary>
        /// Starts the video capture
        /// </summary>      
        public void Start()
        {
            try
            {
                // for safety, call stop, just in case we are already running
                this.Stop();

                // setup a capture window
                mCapHwnd = capCreateCaptureWindowA("WebCap", 0, 0, 0, m_Width, m_Height, 0, 0);

                // connect to the capture device
                Application.DoEvents();
                SendMessage(mCapHwnd, WM_CAP_CONNECT, 0, 0);
                SendMessage(mCapHwnd, WM_CAP_SET_PREVIEW, 0, 0);
            }

            catch (Exception ex)
            {
              //  MessageBox.Show("An error ocurred while starting the video capture. Check that your webcamera is connected properly and turned on.\r\n\n" + excep.Message);
                this.Stop();
            }
        }

        /// <summary>
        /// Stops the video capture
        /// </summary>
        public void Stop()
        {
            try
            {
                // disconnect from the video source
                Application.DoEvents();
                SendMessage(mCapHwnd, WM_CAP_DISCONNECT, 0, 0);
            }

            catch (Exception ex)
            { // don't raise an error here.
            }

        }

        #endregion

        public void Prefer()
        {
           try
            {
                SendMessage(mCapHwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0);
            }
           catch (Exception ex)
           {
             //  MessageBox.Show("An error ocurred while capturing the video image. The video capture will now be terminated.\r\n\n" + excep.Message);
           }
        }

        public Image GetFrame()
        {
           try
            {
                // get the next frame;
                SendMessage(mCapHwnd, WM_CAP_GET_FRAME, 0, 0);

                // copy the frame to the clipboard
                SendMessage(mCapHwnd, WM_CAP_COPY, 0, 0);

                // get from the clipboard
                tempObj = Clipboard.GetDataObject();
                tempImg = (System.Drawing.Bitmap)tempObj.GetData(System.Windows.Forms.DataFormats.Bitmap);                   
                return tempImg;
           }
           catch (Exception ex)
           {
             //  MessageBox.Show("An error ocurred while capturing the video image. The video capture will now be terminated.\r\n\n" + excep.Message);
               this.Stop();
           }
           return null;
        }

You hardly can integrate DirectShow's IAMVideoProcAmp and the the code snippet you provided because your GetFrame is using completely different API: Video for Windows . 您几乎无法集成DirectShow的IAMVideoProcAmp和您提供的代码段,因为GetFrame使用的是完全不同的API: Video for Windows

These are two different APIs which possibly share the same video capture device. 这是两个可能共享同一视频捕获设备的不同API。 So, well, there is a chance that you find the same device in DirectShow, then you start building the capture graph, you obtain the interface, the filter will want to accept your brightness changes without starting video capture, then it will want to make them persistent and thus available for the same device via VfW API. 因此,好吧,您有机会在DirectShow中找到相同的设备,然后开始构建捕获图,获得接口,过滤器将要接受亮度变化而无需开始视频捕获,那么它将需要它们是持久的,因此可以通过VfW API在同一设备上使用。 With all these assumptions and complexity you might be fine doing adjustments via DirectShow, while capture via VfW. 考虑到所有这些假设和复杂性,您可以通过DirectShow进行调整,而通过VfW进行捕获。 However, it looks way more reasonable to just move to DirectShow completely. 但是,完全迁移到DirectShow看起来更合理。

Set the Zoom, Focus and Exposure using the following code snippets. 使用以下代码段设置“缩放”,“聚焦”和“曝光”。

videoDevice.SetCameraProperty(
            CameraControlProperty.Zoom,
            zoomValue,
            CameraControlFlags.Manual);

        videoDevice.SetCameraProperty(
            CameraControlProperty.Focus,
            focusValue,
            CameraControlFlags.Manual);

        videoDevice.SetCameraProperty(
            CameraControlProperty.Exposure,
            exposureValue,
            CameraControlFlags.Manual);

To access other camera properties like brightness, contrast see IAMVideoProcAmp implementation. 要访问其他摄像机属性(例如亮度,对比度),请参阅IAMVideoProcAmp实现。

videoDevice.SetVideoProperty(
VideoProcAmpProperty.Brightness,
brightnessValue,
VideoProcAmpFlags.Manual);

videoDevice.SetVideoProperty(
VideoProcAmpProperty.Contrast,
contrastValue,
VideoProcAmpFlags.Manual);

videoDevice.SetVideoProperty(
VideoProcAmpProperty.Saturation,
saturationValue,
VideoProcAmpFlags.Manual);

videoDevice.SetVideoProperty(
VideoProcAmpProperty.Sharpness,
sharpnessValue,
VideoProcAmpFlags.Manual);

videoDevice.SetVideoProperty(
VideoProcAmpProperty.WhiteBalance,
whiteBalanceValue,
VideoProcAmpFlags.Manual);

videoDevice.SetVideoProperty(
VideoProcAmpProperty.BacklightCompensation,
backlightCompensationValue,
VideoProcAmpFlags.Manual);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM