一、前言
因项目需要需关闭相机自身的自动白平衡和自动曝光时间,统统设定为恒定值,开始实验了opencvCvSharp,但是不起作用,故实验了更底层的 DirectShowLib ,可成功关闭相机自带的自动白平衡和自动曝光时间,再使用 opencvCvSharp 读取摄像头
二、 代码
(1)安装 DirectShowLib 包, 直接在nuget
简单整2按钮2文本框,用于输入需要定义的白平衡温度值和曝光时间值,曝光值-3表示是10的-3次方的意思,值越大则曝光时间越长,图像越亮;白平衡温度值是有范围,可以通过接口 int hr = videoProcAmp.GetRange(prop, out minValue, out maxValue, out steppingDelta, out defaultValue, out flags); 查询获得,温度值越大则偏暖色
(2)重点代码
using DirectShowLib;
using System.Runtime.InteropServices;
using OpenCvSharp;
public class CameraManager
{
private IBaseFilter cameraFilter;
private DsDevice cameraDevice; // DirectShow 设备
public void InitializeCamera()
{
try
{
// 枚举视频输入设备
var devices = DsDevice.GetDevicesOfCat(DirectShowLib.FilterCategory.VideoInputDevice);
if (devices.Length == 0)
{
Console.WriteLine("No video input devices found.");
return;
}
// 选择第一个设备(通常是默认相机)
cameraDevice = devices[0];
// 使用 Moniker 来创建相机的 BaseFilter 对象
object cameraObject = null;
Guid iid = typeof(IBaseFilter).GUID;
cameraDevice.Mon.BindToObject(null, null, ref iid, out cameraObject);
cameraFilter = cameraObject as IBaseFilter;
if (cameraFilter == null)
{
Console.WriteLine("Failed to create camera filter.");
return;
}
Console.WriteLine("Camera initialized successfully.");
}
catch (Exception ex)
{
Console.WriteLine($"Error initializing camera: {ex.Message}");
}
}
// Getter 方法获取相机的 BaseFilter 对象
public IBaseFilter GetCameraFilter()
{
return cameraFilter;
}
// 释放相机资源
public void CloseCamera()
{
if (cameraFilter != null)
{
Marshal.ReleaseComObject(cameraFilter);
cameraFilter = null;
}
cameraDevice = null;
Console.WriteLine("Camera resources released.");
}
}
private void button3_Click(object sender, EventArgs e) {
int expos_v = int.Parse(textBox2.Text);
int wb_v = int.Parse(textBox3.Text);
int hr;
CameraManager cameraManager = new CameraManager();
cameraManager.InitializeCamera();
IBaseFilter cameraFilter = cameraManager.GetCameraFilter();
if (cameraFilter != null)
{
// 在这里可以继续操作相机,比如设置属性、连接到视频源等
// 例如关闭相机的自动白平衡:
//
IAMCameraControl cameraControl = cameraFilter as IAMCameraControl;
if (cameraControl != null)
{
hr = cameraControl.Set(DirectShowLib.CameraControlProperty.Exposure, expos_v, DirectShowLib.CameraControlFlags.Manual/* 设置关闭白平衡的值 */);
DsError.ThrowExceptionForHR(hr);
}
IAMVideoProcAmp videoProcAmp = cameraFilter as IAMVideoProcAmp;
if (videoProcAmp != null)
{
// 获取 WhiteBalance 属性
VideoProcAmpProperty prop = VideoProcAmpProperty.WhiteBalance;
// 获取当前值
int minValue, maxValue, steppingDelta, defaultValue;
VideoProcAmpFlags flags;
// 这一句获取白平衡参数,范围2800-6500 ,默认是4600
//int hr = videoProcAmp.GetRange(prop, out minValue, out maxValue, out steppingDelta, out defaultValue, out flags);
hr = videoProcAmp.Set(prop, wb_v, VideoProcAmpFlags.Manual);
if (hr >= 0)
{
textBox1.Text = "白平衡设置成功";
}
else
{
textBox1.Text = "白平衡设置失败";
}
}
else
{
}
}
}
private void button4_Click(object sender, EventArgs e)
{
// 打开摄像头
using (VideoCapture capture = new VideoCapture(0 , VideoCaptureAPIs.DSHOW ))
{
// 设置分辨率和帧率
// 检查摄像头是否成功打开
if (!capture.IsOpened())
{
Console.WriteLine("无法打开摄像头.");
return;
}
capture.Set(VideoCaptureProperties.FrameWidth,3840 ); // 设置宽度
capture.Set(VideoCaptureProperties.FrameHeight, 2880); // 设置高度
capture.Set(VideoCaptureProperties.FourCC, VideoWriter.FourCC('M', 'J', 'P', 'G'));
//capture.Set(VideoCaptureProperties.Fps, 20); // 设置帧率
// 获取摄像头的宽度和高度
int width = (int)capture.Get(VideoCaptureProperties.FrameWidth);
int height = (int)capture.Get(VideoCaptureProperties.FrameHeight);
// 创建窗口以显示图像
string windowName = $"sp{width}*{height}";
Cv2.NamedWindow(windowName);
Cv2.NamedWindow("cap");
// 循环获取并显示图像
int count = 0;
while (true)
{
count++;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// 从摄像头捕获一帧图像
Mat frame = new Mat();
capture.Read(frame);
stopwatch.Stop();
//textBox1.Text = $"Milliseconds elapsed: {count}";
// 检查是否成功捕获图像
if (frame.Empty())
{
Console.WriteLine("无法从摄像头捕获图像.");
break;
}
// 在窗口中显示图像
Cv2.ImShow(windowName , frame);
// 等待并检测按键,按下 ESC 键退出循环
int key = Cv2.WaitKey(1);
if (key == 27) // ASCII码 27 表示 ESC 键
break;
else if (key == 32) // ASCII码 27 表示 ESC 键
{
Cv2.ImShow("cap", frame);
Cv2.ImWrite("cap.png", frame);
}
}
// 释放资源
capture.Release();
Cv2.DestroyAllWindows();
}
}
三、效果
白平衡温度值3000
白平衡温度值6200