using OpenCvSharp;
using OpenCvSharp.Extensions;
using PaintDotNet.Setting;
using StageController;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace PaintDotNet
{
public class AutoFocusWorkflow
{
public static bool IsWorking;
public static double CurrentValue;
public static void Stop()
{
IsWorking = false;
}
///
/// 自动聚焦的线程方法
///
public static string AutoFocus(AxisController stage, Func CurrentImage)
{
if (!stage.IsOpen) return "载物台离线";
if (IsWorking) return "正在聚焦中......";
IsWorking = true;
int round = 0;//翻转次数
double pulse = FocusingParameter.getRuleFocus().StepLength;
var focusRange = pulse * 5;
double lastMaxMean = 0.0;
double maxMeanValue = 0.0;
int dir = -1; //方向
double trip = 0.0;
try
{
while (IsWorking)
{
stage.WaitMoveDone();
stage.SetSpeedZ(Math.Max((AxisController.ControllerType.Equals("HDS") ? 200 : 80) / (round + 1), 17));
Bitmap m_bitmap = CurrentImage();
CurrentValue = getMeanValueOfBitmap(m_bitmap);
Console.WriteLine(string.Format("自动聚焦:{0:f3} Z:{1:f3}", CurrentValue, stage.Z));
bool foundNextMaxMean = false;
if (CurrentValue > lastMaxMean)
{
foundNextMaxMean = true;
lastMaxMean = CurrentValue;
}
if (CurrentValue > maxMeanValue)
{
maxMeanValue = CurrentValue;
}
if (!foundNextMaxMean)
{
dir = -dir;
if (pulse == 1) //结束
{
if (dir > 0)
stage.Up(1.7);
else
stage.Up(-0.6);
// MessageBox.Show("Done.");
return "";
}
Console.WriteLine("Reverse:" + (dir > 0 ? "+" : "-"));
round++;
lastMaxMean = 0;
pulse = (int)(Math.Max(1, pulse * 0.3));
}
trip += pulse * dir;
if (Math.Abs(trip) > focusRange)
{
return "超出聚焦行程,聚焦结束";
}
if (AxisController.ControllerType.Equals("HDS") && pulse <= 2 && pulse >= -2) //结束
return "聚焦到最小距离,聚焦结束";
stage.Up(pulse * dir);
}
return "聚焦中断";
}
catch (Exception ex)
{
return "聚焦中断";
}
finally
{
stage.WaitMoveDone();
IsWorking = false;
stage.FreeZ();
}
}
public static void AutoFocusFast(AxisController stage, Func CurrentImage)
{
if (IsWorking)
return;
IsWorking = true;
int round = 0;//翻转次数
double pulse = FocusingParameter.getRuleFocus().StepLength / 4;//最小步长1.25um
double lastValue = 0.0;
int dir = -1; //方向
double trip = 0.0;
//stage.SetSpeedZ(40);
try
{
while (IsWorking)
{
//Console.Write("Before focus:");
stage.WaitMoveDone();
//Console.Write("自动聚焦:");
Thread.Sleep(40);
try
{
Bitmap m_bitmap = CurrentImage();
CurrentValue = getMeanValueOfBitmap(m_bitmap);
//Console.WriteLine(string.Format("{0:f3} Z:{1:f3}", m_CurrentValue, stage.Z));
}
catch (Exception ex)
{
return;
}
if (round > 1) return;
else if (lastValue == 0) ;
else if (CurrentValue > lastValue)
{
round = 1;
}
else
{
//Console.WriteLine("Reverse:" + (dir > 0 ? "+" : "-"));
round++;
dir = -dir;
}
lastValue = CurrentValue;
trip += pulse * dir;
if (Math.Abs(trip) > pulse * 5)
{
Console.WriteLine("Trip of Z out of autofocus range.");
return;
}
stage.Up(pulse * dir);
}
}
catch
{
}
finally
{
// Console.Write("End focus:");
stage.WaitMoveDone();
//m_CurrentValue = getMeanValueOfBitmap(CurrentImage());
//Console.WriteLine(string.Format("聚焦完成:{0:f3} Z:{1:f3}", m_CurrentValue, stage.Z));
IsWorking = false;
// stage.LockZ();
}
}
///
/// 获取输入图片的清晰度
///
///
///
private static double getMeanValueOfBitmap(Bitmap bitmap)
{
Mat converted = PaintDotNet.Camera.Tools.ToMat(bitmap);
Mat imageGrey = new Mat();
Mat imageSobel = new Mat();
try
{
if (converted.Channels() == 3)
OpenCvSharp.Cv2.CvtColor(converted, imageGrey, OpenCvSharp.ColorConversionCodes.RGB2GRAY);
else if (converted.Channels() == 1)
imageGrey = converted;
}
catch (Exception)
{
imageGrey = converted;
}
OpenCvSharp.Mat meanValueImage = new OpenCvSharp.Mat();
OpenCvSharp.Mat meanStdValueImage = new OpenCvSharp.Mat();
//求灰度图像的标准差 值越大越好
OpenCvSharp.Cv2.MeanStdDev(imageGrey, meanValueImage, meanStdValueImage);
return meanStdValueImage.At(0, 0);
}
}
}