using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Lumenera.USB;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System.Drawing;
using System.Windows.Interop;
using System.Threading;
using OpenCvSharp.Dnn;
using System.Windows.Media.Animation;
namespace TIASshot {
/// <summary>
/// Lumeneraカメラクラス
/// </summary>
internal class Lucam {
public string DeviceName { get; private set; } = "Unknown";
public string SerialNumber { get; private set; }
public string ErrorMsg { get; private set; }
private IntPtr _hCam = IntPtr.Zero;
private PictureBox _picPreview, _picDisplay;
private Form1 _form;
private bool _isPreview = false;
private bool _check = false;
private int _calibrating = 0;
private dll.LucamSnapshot _snap;
private dll.LucamConversion _convert;
private dll.LucamRgbPreviewCallback _callbackHandler;
private int _callbackId;
//private int _count = 0;
private Bitmap[] _bmps = new Bitmap[2];
private int _bmpIndex = 0;
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="preview"></param>
/// <param name="display"></param>
public Lucam(Form1 form, PictureBox preview, PictureBox display) {
_picPreview = preview;
_picDisplay = display;
_form = form;
// Default value for taking a snapshot.
_snap.BufferLastFrame = false;
_snap.Exposure = 20;
_snap.ExposureDelay = 0;
_snap.flReserved1 = 0;
_snap.flReserved2 = 0;
_snap.Format.BinningX = 1;
_snap.Format.BinningY = 1;
_snap.Format.FlagsX = 0;
_snap.Format.FlagsY = 0;
_snap.Format.Height = 1024;
_snap.Format.PixelFormat = dll.LucamPixelFormat.PF_8;
_snap.Format.SubSampleX = 1;
_snap.Format.SubSampleY = 1;
_snap.Format.Width = 1280;
_snap.Format.X = 0;
_snap.Format.Y = 0;
_snap.Gain = 2.0f;
_snap.GainBlue = 1;
_snap.GainGrn1 = 1;
_snap.GainGrn2 = 1;
_snap.GainRed = 1;
_snap.ShutterType = dll.LucamShutterType.GlobalShutter;
_snap.StrobeDelay = 0.1f;
_snap.StrobeFlags = 0;
_snap.Timeout = 5000;
_snap.ulReserved2 = 0;
_snap.UseHwTrigger = false;
_convert.DemosaicMethod = dll.LucamDemosaicMethod.HIGH_QUALITY;
_convert.CorrectionMatrix = dll.LucamCorrectionMatrix.LED;
}
/// <summary>
/// カメラ接続
/// </summary>
/// <returns></returns>
public bool Connect() {
var numCam = dll.LucamNumCameras();
if ( numCam < 1 ) {
ErrorMsg = "カメラが見つかりません.\r\n終了します.";
return false;
}
if (numCam > 1) {
ErrorMsg = "複数のカメラが見つかりました.\r\n正しいカメラを1つ接続してください.\r\n終了します.";
return false;
}
var lumVersion = new dll.LucamVersion[numCam];
lumVersion = api.EnumCameras();
var id = 0;
if (lumVersion[id].CameraId == 0x49f) DeviceName = "Lw110";
SerialNumber = lumVersion[id].SerialNumber.ToString();
_hCam = api.CameraOpen(1);
if (_hCam == IntPtr.Zero) {
return false;
}
_callbackHandler = new dll.LucamRgbPreviewCallback(PreviewCallback);
_callbackId = dll.LucamAddRgbPreviewCallback(_hCam, _callbackHandler, IntPtr.Zero, dll.LucamPixelFormat.PF_24);
if (_callbackId == -1) {
ErrorMsg = "コールバックの登録に失敗しました.\r\n終了します.";
return false;
}
return true;
}
/// <summary>
/// プレビュー開始・停止
/// </summary>
/// <returns></returns>
public bool StartStopPreview() {
if (_isPreview) {
//dll.LucamRemoveRgbPreviewCallback(_hCam, _callbackId);
//Debug.WriteLine("CB解除");
var ret = dll.LucamStreamVideoControl(_hCam, dll.LucamStreamMode.STOP_STREAMING, _picPreview.Handle.ToInt32());
Debug.WriteLine("プレビュー停止");
if (!ret) {
return false;
}
_isPreview = false;
return true;
} else {
var ret = dll.LucamStreamVideoControl(_hCam, dll.LucamStreamMode.START_DISPLAY, _picPreview.Handle.ToInt32());
if (!ret) {
return false;
}
_isPreview = true;
return true;
}
}
/// <summary>
/// 画像表示(スレッドセーフ)
/// </summary>
void SafeDisplay() {
if (_picDisplay.InvokeRequired) {
_picDisplay.Invoke((MethodInvoker)delegate { SafeDisplay(); });
return;
}
_picDisplay.Image = _bmps[_bmpIndex];
}
/// <summary>
/// プレビューコールバック
/// </summary>
/// <param name="pContext"></param>
/// <param name="pData">データポインタ</param>
/// <param name="n">データサイズ</param>
/// <param name="unused"></param>
void PreviewCallback(IntPtr pContext, IntPtr pData, int n, uint unused) {
//Debug.WriteLine(n);
using (Mat img = Mat.FromPixelData(1024, 1280, MatType.CV_8UC3, pData)) {
using (Mat imgt = img.T()) {
_bmps[_bmpIndex] = imgt.ToBitmap();
Scalar m;
using (Mat mask = new Mat(imgt.Size(), MatType.CV_8UC1)) {
Cv2.Rectangle(mask, new Rect(300, 165, 100, 100), new Scalar(255), Cv2.FILLED);
m = Cv2.Mean(imgt, mask);
}
if (_check || _calibrating > 0) {
Debug.WriteLine(m);
_check = false;
}
if (_calibrating > 0 && _calibrating % 5 == 0) {
float target = 230;
float rate = 0.5F;
float mb = target / (float)m.Val0;
float mg = target / (float)m.Val1;
float mr = target / (float)m.Val2;
mb = (mb - 1.0F) * (m.Val0 > 254 ? 1.0F : rate) + 1.0F;
mg = (mg - 1.0F) * (m.Val1 > 254 ? 1.0F : rate) + 1.0F;
mr = (mr - 1.0F) * (m.Val2 > 254 ? 1.0F : rate) + 1.0F;
float value;
dll.LucamPropertyFlag flag;
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_BLUE, out value, out flag);
Debug.WriteLine($"Gain Blue {value} * {mb} -> {value * mb} ({flag})");
value *= mb;
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN_BLUE, value, flag);
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_GREEN1, out value, out flag);
Debug.WriteLine($"Gain Green1 {value} * {mg} -> {value * mg}");
value *= mg;
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN_GREEN1, value, flag);
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_GREEN2, out value, out flag);
Debug.WriteLine($"Gain Green2 {value} * {mg} -> {value * mg}");
value *= mg;
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN_GREEN2, value, flag);
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_RED, out value, out flag);
Debug.WriteLine($"Gain Red {value} * {mr} -> {value * mr}");
value *= mr;
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN_RED, value, flag);
}
if (_calibrating > 0) _calibrating--;
}
}
//SafeDisplay();
_picDisplay.Image = _bmps[_bmpIndex];
_bmpIndex = (_bmpIndex + 1) % 2;
if (_bmps[_bmpIndex] != null) _bmps[_bmpIndex].Dispose();
}
/// <summary>
/// 画像撮影1枚
/// </summary>
public void ShotOne() {
Shot();
}
/// <summary>
/// 複数画像撮影
/// </summary>
public void ShotMulti() {
Shot(5, 1000);
}
/// <summary>
/// 撮影
/// </summary>
/// <param name="numImages"></param>
/// <param name="interval"></param>
private void Shot(int numImages=1, int interval = 1000) {
SetSnapParam();
dll.LucamEnableFastFrames(_hCam, ref _snap);
var imageSize = _snap.Format.Width * _snap.Format.Height;
var rawImage = new byte[imageSize];
var rgbImage = new byte[imageSize * 3];
for (var i = 0; i < numImages; i++) {
var ret = dll.LucamTakeFastFrame(_hCam, rawImage);
//Debug.WriteLine(ret);
if (i < numImages - 1) Thread.Sleep(interval);
dll.LucamConvertFrameToRgb24(_hCam, rgbImage, rawImage, _snap.Format.Width, _snap.Format.Height, dll.LucamPixelFormat.PF_8, ref _convert);
using (Mat img = Mat.FromPixelData(1024, 1280, MatType.CV_8UC3, rgbImage)) {
Cv2.ImWrite($"orig_{i:00}.jpg", img);
using (Mat imgt = img.T()) {
Cv2.ImWrite($"snap_{i:00}.jpg", imgt);
}
}
}
rgbImage = null;
rawImage = null;
dll.LucamDisableFastFrames(_hCam);
}
public void Calibration() {
Debug.WriteLine("校正前");
SetSnapParam();
dll.LucamOneShotAutoExposure(_hCam, 150, 0, 0, _snap.Format.Width, _snap.Format.Height);
//dll.LucamOneShotAutoExposure(_hCam, 100, 165, 300, 100, 100);
//Thread.Sleep(1000);
//dll.LucamOneShotAutoExposure(_hCam, 200, 165, 300, 100, 100);
//Thread.Sleep(1000);
//dll.LucamOneShotAutoExposure(_hCam, 200, 165, 300, 100, 100);
dll.LucamOneShotAutoWhiteBalance(_hCam, 0, 0, _snap.Format.Width, _snap.Format.Height);
//dll.LucamOneShotAutoWhiteBalance(_hCam, 165, 300, 100, 100);
Debug.WriteLine("校正後");
SetSnapParam();
_calibrating = 30;
}
private void SetSnapParam() {
dll.LucamPropertyFlag flag;
float value = 0;
dll.LucamGetProperty(_hCam, dll.LucamProperty.EXPOSURE, out value, out flag);
_snap.Exposure = value;
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN, out value, out flag);
_snap.Gain = value;
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_BLUE, out value, out flag);
_snap.GainBlue = value;
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_GREEN1, out value, out flag);
_snap.GainGrn1 = value;
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_GREEN2, out value, out flag);
_snap.GainGrn2 = value;
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_RED, out value, out flag);
_snap.GainRed = value;
Debug.WriteLine($"Exp {_snap.Exposure} Gain {_snap.Gain} GainBlue {_snap.GainBlue} GainGrn1 {_snap.GainGrn1} GainGrn2 {_snap.GainGrn2} GainRed {_snap.GainRed}");
}
public void Check() {
_check = true;
}
/// <summary>
/// カメラ切断
/// </summary>
public void Disconnect() {
if (_hCam != IntPtr.Zero) {
if (_isPreview) {
StartStopPreview();
}
api.CameraClose(_hCam);
_hCam = IntPtr.Zero;
Debug.WriteLine("カメラ切断");
}
}
}
}