using System;
using System.Collections.Concurrent;
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.Aruco;
using System.Windows.Media.Animation;
using System.Configuration;
using System.Web.ModelBinding;
using System.Windows.Controls;
using System.IO;
using static System.Resources.ResXFileRef;
using System.Windows.Shapes;
using Path = System.IO.Path;
using OpenCvSharp.Dnn;
namespace TIASshot {
/// <summary>
/// Lumeneraカメラクラス
/// </summary>
internal class Lucam : CameraBase {
// 光源の輝度設定
// 連続撮影のマルチスレッド化
// GUI更新はタイマー使用に変更
IntPtr _hCam = IntPtr.Zero;
byte[] _rawImage;
byte[] _rgbImage;
PictureBox _picPreview;
dll.LucamSnapshot _snap;
dll.LucamConversion _convert;
dll.LucamRgbPreviewCallback _callbackHandler;
int _callbackId;
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="preview"></param>
/// <param name="display"></param>
public Lucam(Form1 form, PictureBox preview) : base(form) {
_picPreview = preview;
// カメラパラメータの初期値
_snap.BufferLastFrame = false;
_snap.Exposure = Config.GetFloat("Lucam/Exposure");
_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 = Config.GetFloat("Lucam/Gain");
_snap.GainBlue = Config.GetFloat("Lucam/GainB");
_snap.GainGrn1 = Config.GetFloat("Lucam/GainG");
_snap.GainGrn2 = _snap.GainGrn1;
_snap.GainRed = Config.GetFloat("Lucam/GainR");
_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 override bool Connect() {
if (!BootCheck()) return false;
int numCam = 0;
try {
numCam = dll.LucamNumCameras();
} catch (Exception ex) {
ErrorMsg = ex.Message;
return false;
}
if ( numCam < 1 ) {
ErrorMsg = "Lucamが見つかりません";
return false;
}
if (numCam > 1) {
ErrorMsg = "複数のLucamが見つかりました.\r\n正しいカメラを1つ接続してください.";
return false;
}
// カメラのデバイス情報取得
var lumVersion = new dll.LucamVersion[numCam];
lumVersion = api.EnumCameras();
var id = 0;
if (lumVersion[id].CameraId == 0x49f) DeviceName = "Lw110";
SetInfo("カメラ型番", DeviceName);
SerialNumber = lumVersion[id].SerialNumber.ToString();
SetInfo("カメラSN", SerialNumber);
// カメラを開く
_hCam = api.CameraOpen(1);
if (_hCam == IntPtr.Zero) {
ErrorMsg = "カメラの接続に失敗しました.\r\n他のアプリケーションでカメラを使用していないか確認してください.";
return false;
}
// プレビューコールバックの登録
_callbackHandler = new dll.LucamRgbPreviewCallback(PreviewCallback);
_callbackId = dll.LucamAddRgbPreviewCallback(_hCam, _callbackHandler, IntPtr.Zero, dll.LucamPixelFormat.PF_24);
if (_callbackId == -1) {
ErrorMsg = "コールバックの登録に失敗しました";
return false;
}
SetCameraParam(); // カメラパラメータの設定
StartStopPreview(); // プレビュー開始
return true;
}
/// <summary>
/// プレビュー開始・停止
/// </summary>
/// <returns></returns>
public bool StartStopPreview() {
if (_isPreview) {
// プレビュー停止
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>
/// <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) {
using (Mat img = Mat.FromPixelData(_snap.Format.Height, _snap.Format.Width, MatType.CV_8UC3, pData)) {
using (Mat imgt = img.T()) {
_bmps[_bmpIndex] = imgt.ToBitmap();
ProcessCalibrationFrame(imgt);
}
}
_form.ShowImage(_bmps[_bmpIndex]);
_bmpIndex = (_bmpIndex + 1) % 2;
if (_bmps[_bmpIndex] != null) _bmps[_bmpIndex].Dispose();
}
/// <summary>
/// ゲイン/ホワイトバランスの反映(Lucam 固有)
/// </summary>
/// <param name="whitePatch">白パッチの計測値</param>
protected override void ApplyWhiteBalance(Scalar whitePatch) {
_snap.GainBlue *= GetRatio((float)whitePatch.Val0, Config.GetFloat("Calib/Reference/B"));
_snap.GainGrn1 *= GetRatio((float)whitePatch.Val1, Config.GetFloat("Calib/Reference/G"));
_snap.GainGrn2 = _snap.GainGrn1;
_snap.GainRed *= GetRatio((float)whitePatch.Val2, Config.GetFloat("Calib/Reference/R"));
SetCameraParam();
}
/// <summary>
/// 校正収束時のゲイン値ログ出力(Lucam 固有)
/// CalcTcc の前に呼ばれ,元コードの Debug.WriteLine 順序を再現する.
/// </summary>
protected override void LogCalibrationConverged() {
Debug.WriteLine($"Gain Blue : {_snap.GainBlue}");
Debug.WriteLine($"Gain Green: {_snap.GainGrn1}");
Debug.WriteLine($"Gain Red : {_snap.GainRed}");
}
/// <summary>
/// 校正完了時のカメラ情報記録(Lucam 固有)
/// CalcTcc の後に呼ばれ,SetInfo で各値を保存する.
/// </summary>
/// <param name="imgt">処理対象 Mat</param>
protected override void RecordCalibrationInfo(Mat imgt) {
SetInfo("Exposure(ms)", $"{_snap.Exposure}");
SetInfo("Gain", $"{_snap.Gain}");
SetInfo("Gain B", $"{_snap.GainBlue}");
SetInfo("Gain G", $"{_snap.GainGrn1}");
SetInfo("Gain R", $"{_snap.GainRed}");
SetInfo("画像幅", $"{imgt.Width}");
SetInfo("画像高さ", $"{imgt.Height}");
}
/// <summary>
/// 撮影
/// </summary>
/// <param name="numImages"></param>
/// <param name="interval"></param>
protected override void Shot(int numImages=1, int interval=0) {
SetSnapParam();
_shots = new BlockingCollection<Mat>();
var thread = new Thread(() => SaveThread(numImages));
thread.Start();
BeginShot();
RunShotLoop(numImages, interval);
EndShot();
}
/// <summary>
/// 撮影開始処理(Lucam 固有)
/// </summary>
protected override void BeginShot() {
dll.LucamEnableFastFrames(_hCam, ref _snap);
var imageSize = _snap.Format.Width * _snap.Format.Height;
_rawImage = new byte[imageSize];
_rgbImage = new byte[imageSize * 3];
}
/// <summary>
/// 1 フレーム取得(Lucam 固有)
/// </summary>
/// <returns>撮影した Mat(呼び出し元が _shots に追加する)</returns>
protected override Mat CaptureFrame() {
var ret = dll.LucamTakeFastFrame(_hCam, _rawImage);
//Debug.WriteLine(ret);
dll.LucamConvertFrameToRgb24(_hCam, _rgbImage, _rawImage,
_snap.Format.Width, _snap.Format.Height, dll.LucamPixelFormat.PF_8, ref _convert);
using (Mat img = Mat.FromPixelData(_snap.Format.Height, _snap.Format.Width, MatType.CV_8UC3, _rgbImage)) {
return img.T();
}
}
/// <summary>
/// 撮影終了処理(Lucam 固有)
/// </summary>
protected override void EndShot() {
_rgbImage = null;
_rawImage = null;
dll.LucamDisableFastFrames(_hCam);
}
/// <summary>
/// 撮影パラメータの設定
/// </summary>
private void SetSnapParam() {
dll.LucamPropertyFlag flag;
dll.LucamGetProperty(_hCam, dll.LucamProperty.EXPOSURE, out _snap.Exposure, out flag);
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN, out _snap.Gain, out flag);
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_BLUE, out _snap.GainBlue, out flag);
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_GREEN1, out _snap.GainGrn1, out flag);
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_GREEN2, out _snap.GainGrn2, out flag);
dll.LucamGetProperty(_hCam, dll.LucamProperty.GAIN_RED, out _snap.GainRed, out flag);
Debug.WriteLine($"SetSnapParam Exp {_snap.Exposure} Gain {_snap.Gain} GainBlue {_snap.GainBlue} GainGrn1 {_snap.GainGrn1} GainGrn2 {_snap.GainGrn2} GainRed {_snap.GainRed}");
}
/// <summary>
/// カメラパラメータの設定
/// </summary>
private void SetCameraParam() {
var flag = dll.LucamPropertyFlag.NONE;
dll.LucamSetProperty(_hCam, dll.LucamProperty.EXPOSURE, _snap.Exposure, flag);
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN, _snap.Gain, flag);
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN_BLUE, _snap.GainBlue, flag);
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN_GREEN1, _snap.GainGrn1, flag);
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN_GREEN2, _snap.GainGrn2, flag);
dll.LucamSetProperty(_hCam, dll.LucamProperty.GAIN_RED, _snap.GainRed, flag);
Debug.WriteLine($"SetCameraParam Exp {_snap.Exposure} Gain {_snap.Gain} GainBlue {_snap.GainBlue} GainGrn1 {_snap.GainGrn1} GainGrn2 {_snap.GainGrn2} GainRed {_snap.GainRed}");
}
/// <summary>
/// カメラ切断
/// </summary>
public override void Disconnect() {
if (_hCam != IntPtr.Zero) {
if (_isPreview) {
StartStopPreview();
}
api.CameraClose(_hCam);
_hCam = IntPtr.Zero;
Debug.WriteLine("カメラ切断");
}
}
}
}