前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C# 探测器测试系统

C# 探测器测试系统

作者头像
zls365
发布2020-08-19 11:46:45
1.4K0
发布2020-08-19 11:46:45
举报

运行效果:

重要知识点:

  1. 控件循环遍历操控;
  2. 队列数组的应用: private Queue<double>[] dataQueue = new Queue<double>[8]; //把Queue<double>看成一个类型 int[] a=new int [8]

3. 委托与线程,主要是为了界面实时刷新显示数据;

4. 窗体最大化而不遮挡任务栏;

5. 数据解码,标准差、均值等运算.

主窗体MainForm.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Xml;
using BLL;

using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms.DataVisualization.Charting;


namespace ThzDataProcess
{
    public partial class MainForm : DevComponents.DotNetBar.Office2007Form
    {
        private int frameRate = 8,channel=1;    
        bool isStart = false, isStart1 = false;
        const string stopIcon = @"icon\stop.png";
        const string startIcon = @"icon\start.png";
        DataProcess DPBLL = null;
        object ThreadLock = new object();

        private Queue<double>[] dataQueue = new Queue<double>[8];//把Queue<double>看成一个类型 int[] a=new int [8]
        public MainForm()
{
            this.DoubleBuffered = true;//设置本窗体
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲


            this.EnableGlass = false;
            InitializeComponent();

            InitChart();
            string DeviceIP = "192.168.1.120";
            int LocalPort = 8009;
            DPBLL = new DataProcess(DeviceIP, LocalPort);

            DPBLL.ShowEvent_zyr1 = dataShow;
            DPBLL.ShowEvent_zyr2 = chartShow;
            DPBLL.Start();//启动线程

            radioButton1.Checked = true;
            radioButton2.Checked = false;

            dataQueue[0] = new Queue<double>(100);
            dataQueue[1] = new Queue<double>(100);
            dataQueue[2] = new Queue<double>(100);
            dataQueue[3] = new Queue<double>(100);
            dataQueue[4] = new Queue<double>(100);
            dataQueue[5] = new Queue<double>(100);
            dataQueue[6] = new Queue<double>(100);
            dataQueue[7] = new Queue<double>(100);


        }
        // 防止闪屏        
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }



        private void MainForm_Load(object sender, EventArgs e)
{
            this.WindowState = FormWindowState.Normal;
            this.FormBorderStyle = FormBorderStyle.Sizable;
            this.Top = 0;
            this.Left = 0;
            this.Width = Screen.PrimaryScreen.WorkingArea.Width;
            this.Height = Screen.PrimaryScreen.WorkingArea.Height;
        }

        private void InitChart()
{
            Chart[] ch = new Chart[8] { chart1, chart2 , chart3, chart4, chart5, chart6, chart7, chart8 };
            for (int i = 0; i < 8; i++)
            {
                ch[i].ChartAreas.Clear();
                ChartArea chartArea1 = new ChartArea("C1");
                ch[i].ChartAreas.Add(chartArea1);
                //定义存储和显示点的容器
                ch[i].Series.Clear();
                Series series1 = new Series("S1");
                series1.ChartArea = "C1";
                ch[i].Series.Add(series1);

                ch[i].ChartAreas[0].AxisY.IsStartedFromZero = false;
                ch[i].Legends[0].Enabled = false;

                ch[i].ChartAreas[0].AxisX.Interval = 5;
                ch[i].ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver;
                ch[i].ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver;
                //设置标题
                ch[i].Titles.Clear();
                ch[i].Titles.Add("S01");
                ch[i].Titles[0].Text = "通道" + (i + 1) + " AD折线图显示";
                ch[i].Titles[0].ForeColor = Color.RoyalBlue;
                ch[i].Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
                //设置图表显示样式
                ch[i].Series[0].Color = Color.Red;
                //this.chart1.Titles[0].Text = string.Format("{0}折线图显示", );
                ch[i].Series[0].ChartType = SeriesChartType.Line;
                ch[i].Series[0].Points.Clear();
            }
        }
        public void chartShow( Double y,int ch)
{

            Chart[] chNum = new Chart[8] { chart1, chart2, chart3, chart4, chart5, chart6, chart7, chart8 };
            if(ch <= 8)
               chartDisplay(chNum[ch-1], ch, y);

        }
        delegate void ChartDelegate(Chart chart, int ch, Double y);
        private void chartDisplay(Chart chart, int ch, Double y)
{

            if (chart.InvokeRequired)
            {
                ChartDelegate chartDelegate = chartDisplay;
                chart.Invoke(chartDelegate, new object[] { chart, ch, y });
            }
            else
            {
                if ( isStart == true )
                    UpdateQueueValue(ch,y);
                chart.Series[0].Points.Clear();
                // for (int j = 0; j < 100; j++)
                //     chart1.Series[0].Points.AddXY(j, y);
                for (int i = 0; i < dataQueue[ch-1].Count; i++)
                    chart.Series[0].Points.AddXY((i + 1), dataQueue[ch-1].ElementAt(i));
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
{
            if (!isStart)
            {
                Command.CommandUp_v1(frameRate);
                btnStart.Text = @"停止采集";
                btnStart.DisabledImage = btnStart.Image;
                btnStart.Image = (Image)btnStart.PressedImage.Clone();
                isStart = !isStart;

            }
            else
            {
                Command.CommandUp_v1(0);
                btnStart.Text = @"开始采集";
                btnStart.Image = btnStart.DisabledImage;
                isStart = !isStart;
            }
        }

        private void UpdateQueueValue(int ch,Double y)
{

            if (dataQueue[ch-1].Count > 100)
                //先出列
                dataQueue[ch-1].Dequeue();
            dataQueue[ch-1].Enqueue(y);


        }
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
            Command.CommandUp_v1(0);
        }

        public void dataShow(string avg, string stdDev, string maxMin, int ch)
{
            double temperatureSensitivity = 0.0;
            double dValue = 0.0,temp1=0.0, temp2 = 0.0, tempV1 = 0.0, tempV2 = 0.0;

            //ShowMessage(dataGridViewX1, str, row, column);
            Label[] lb = new Label[48] { label_1,label_2,label_3,label_4,label_5, label_6, label_7, label_8, label_9, label_10 , label_11, label_12, label_13, label_14, label_15,label_16,
                                         label_17,label_18,label_19,label_20,label_21, label_22, label_23, label_24, label_25, label_26 , label_27, label_28, label_29, label_30, label_31,label_32,
                                         label_33,label_34,label_35,label_36,label_37, label_38, label_39, label_40, label_41, label_42 , label_43, label_44, label_45, label_46, label_47,label_48 };

            if (ch <= 8 && isStart == true)
            {
                if (radioButton1.Checked == true)
                {

                    ShowMessage(lb[(ch - 1) * 6], "V1 : " + avg);
                    ShowMessage(lb[(ch - 1) * 6 + 1], "σ1 : " + stdDev);
                    ShowMessage(lb[(ch - 1) * 6 + 2], "Max/Min :" + maxMin);
                
                }
                else
                {
                    ShowMessage(lb[(ch - 1) * 6 + 3], "V2 : " + avg);
                    ShowMessage(lb[(ch - 1) * 6 + 4], "σ2 : " + stdDev);
                    ShowMessage(lb[(ch - 1) * 6 + 2], "Max/Min :" + maxMin);
                }

                if (textBox1.Text != "" && textBox2.Text != "")
                {
                    dValue = Math.Abs(Convert.ToDouble(textBox1.Text) - Convert.ToDouble(textBox2.Text));
                    temp1 = Convert.ToDouble(lb[(ch - 1) * 6 + 1].Text.Substring(5, lb[(ch - 1) * 6 + 1].Text.Length - 5));
                    temp2 = Convert.ToDouble(lb[(ch - 1) * 6 + 4].Text.Substring(5, lb[(ch - 1) * 6 + 4].Text.Length - 5));
                    tempV1 = Convert.ToDouble(lb[(ch - 1) * 6].Text.Substring(5, lb[(ch - 1) * 6].Text.Length - 5));
                    tempV2 = Convert.ToDouble(lb[(ch - 1) * 6 + 3].Text.Substring(5, lb[(ch - 1) * 6 + 3].Text.Length - 5));
                    if (tempV1 - tempV2 != 0)
                        temperatureSensitivity = (temp1 + temp2) * dValue / Math.Abs(tempV1 - tempV2) / 2.0;
                    ShowMessage(lb[(ch - 1) * 6 + 5], "ΔT :" + temperatureSensitivity.ToString("0.00"));
                }

            }
            else
            {
                ;
            }
        }

       

        delegate void ShowMessageDelegate(Label lbl, string message);
        private void ShowMessage(Label lbl, string message)
{
            if (lbl.InvokeRequired)
            {
                ShowMessageDelegate showMessageDelegate = ShowMessage;
                lbl.Invoke(showMessageDelegate, new object[] { lbl, message});
            }
            else
            {

                lbl.Text = message;
            }
        }

       
    }
}

类DataCalculate.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ThzData;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Drawing;

using ThzDataProcess;
using System.Windows.Forms;


namespace BLL
{
    class DataCalculate
    {

       
        DataProcess dp = null;
        public  void tempartureData_zyr(List<byte[]> Zhendata, Action<string> ShowEvent_zyr2)
        {
            StringBuilder sNeed = new StringBuilder();
           
            foreach (Byte[] match in Zhendata)
                sNeed.Append(BitConverter.ToString(match).Replace("-", "").Substring(20).ToUpper());
            double[] temparture = GetTemparture_zyr(sNeed.ToString());
            // mf.ShowlbDevTem(string.Format("设备温度:\nT1:{0:N}°\nT2:{1:N}°\nT3:{2:N}°\nT4:{3:N}°", temparture[0], temparture[1], temparture[2], temparture[3]));
            ShowEvent_zyr2(string.Format("设备温度:\nT1:{0:N}°\nT2:{1:N}°\nT3:{2:N}°\nT4:{3:N}°", temparture[0], temparture[1], temparture[2], temparture[3]));
           // dp.callBack_zyr2(string.Format("设备温度:\nT1:{0:N}°\nT2:{1:N}°\nT3:{2:N}°\nT4:{3:N}°", temparture[0], temparture[1], temparture[2], temparture[3]));
            sNeed.Clear();
            foreach (var tem in temparture)
                sNeed.Append(tem + "***");
            strWrite_zyr(sNeed.ToString(), Environment.CurrentDirectory + "\\bin", "tempartureData.txt");
            sNeed.Clear();


        }

        public double[] GetTemparture_zyr(string str)
        {
            string tepStr = str.Substring(20 * 2, 8 * 2);
            double[] Temparture = new double[4];
            if (tepStr == null)
                return Temparture;
            byte[] Wen = DataProcess.strToToHexByte(tepStr);
            if ((Wen[0] & 0xf0) >> 4 == 15)
                Temparture[0] = -(~Wen[1] + 1 + 256.0 * ~Wen[0]) / 16;
            else
                Temparture[0] = (Wen[1] + 256.0 * Wen[0]) / 16;

            if ((Wen[2] & 0xf0) >> 4 == 15)
                Temparture[1] = -(~Wen[3] + 1 + 256.0 * ~Wen[2]) / 16;
            else
                Temparture[1] = (Wen[3] + 256.0 * Wen[2]) / 16;

            if ((Wen[4] & 0xf0) >> 4 == 15)
                Temparture[2] = -(~Wen[5] + 1 + 256.0 * ~Wen[4]) / 16;
            else
                Temparture[2] = (Wen[5] + 256.0 * Wen[4]) / 16;

            if ((Wen[6] & 0xf0) >> 4 == 15)
                Temparture[3] = -(~Wen[7] + 1 + 256.0 * ~Wen[6]) / 16;
            else
                Temparture[3] = (Wen[7] + 256.0 * Wen[6]) / 16;
            return Temparture;
        }
        int zhenRows = 0;
        public void adDataCaculate_zyr(List<byte[]> Zhendata, Action<string, string, string,int> ShowEvent_zyr1, Action<double,int> ShowEvent_zyr2)
        {
            //byte[] byteData = new byte[35250];//1410*25
           
            int count1 = 0, count2 = 0,sampleCount=0;
            StringBuilder sNeed = new StringBuilder();
            StringBuilder sNeed1 = new StringBuilder();
            //MainForm mf = new MainForm();

            sampleCount = Zhendata[0][28] * 256 + Zhendata[0][29];
            byte[] byteData = new byte[Zhendata.Count()* 1410];//1410*44
            foreach (Byte[] Package in Zhendata)
            {
                count1 = 0;
                foreach (byte byt in Package)
                {
                    if (count1 >= 10)   //跳过第一个数
                    {

                        byteData[count2] = byt;
                        count2++;

                    }
                    count1++;
                }
            }
            // Console.ReadKey();
            double[] channel = new double[sampleCount];//473、465
            double[] channel1 = new double[sampleCount];
            double variance = 0.0, average_original = 0.0 , average_converted = 0.0,stdDev = 0.0,maxNum= 0.0,minNum = 0.0;
            for (int i = 0; i < 36; i++)
            {
                for (int j = 0; j < sampleCount; j++)
                {
                    byte bigByte = Convert.ToByte(byteData[j * 74 + i * 2 + 40].ToString("X"), 16);
                    if ((bigByte & 0xf0) >> 4 == 15)
                    {
                        channel[j] = -(~byteData[j * 74 + i * 2 + 41] + 1 + 256.0 * ~byteData[j * 74 + i * 2 + 40]) / 8192.0 * 5;//2^12 =4096
                        channel1[j] = -(~byteData[j * 74 + i * 2 + 41] + 1 + 256.0 * ~byteData[j * 74 + i * 2 + 40]);
                    }
                    else
                    {
                        channel[j] = (byteData[j * 74 + i * 2 + 41] + 256.0 * byteData[j * 74 + i * 2 + 40]) / 8192.0 * 5;
                        channel1[j] = (byteData[j * 74 + i * 2 + 41] + 256.0 * byteData[j * 74 + i * 2 + 40]) ;
                    }
                    sNeed.Append(channel[j] + ",");
                    sNeed1.Append(channel1[j] + ",");
                }

                Stopwatch elapsetime = new Stopwatch();
                elapsetime.Start();


                stdDev = CalculateStdDev(channel)*1000;//标准差
                average_converted = channel.Average()*1000;
                maxNum = channel.Max()*1000;
                minNum = channel.Min()*1000;
                average_original = channel.Average();

                ShowEvent_zyr1(average_converted.ToString("0.00"), stdDev.ToString("0.00") ,maxNum.ToString("0.00")+"/"+minNum.ToString("0.00"),i+1);
                ShowEvent_zyr2(average_original, i+1);

                elapsetime.Stop();
                Console.WriteLine(elapsetime.ElapsedMilliseconds.ToString("000"));

                //variance = Var_zyr(channel);//方差
                // ShowEvent_zyr1(zhenRows, 2 * i + 1, variance.ToString());
                //sNeed.Append("***variance:" + variance + "***average:");

                //ShowEvent_zyr1(zhenRows, 2 * i, average.ToString());
                // ShowEvent_zyr3(i+1,average);
                //sNeed.Append(average);
                //strWrite_zyr(sNeed.ToString(), Environment.CurrentDirectory + "\\bin", "channelData.txt");
                //sNeed.Clear();
            }
            zhenRows++;
        }

       // private static double CalculateStdDev(IEnumerable<double> values)
             private static double CalculateStdDev(double[] values)
        {
            double ret = 0;
            if (values.Count() > 0)
            {
                //  计算平均数   
                double avg = values.Average();
                //  计算各数值与平均数的差值的平方,然后求和 
                double sum = values.Sum(d => Math.Pow(d - avg, 2));
                //  除以数量,然后开方
                ret = Math.Sqrt(sum / values.Count());
            }
            return ret;
        }

        public double Var_zyr(double[] v)
        {
            double sum1 = 0;
            for (int i = 0; i < v.Length; i++)
            {
                double temp = v[i] * v[i];
                sum1 = sum1 + temp;
            }

            double sum = 0;
            foreach (double d in v)
            {
                sum = sum + d;
            }
            double var = sum1 / v.Length - (sum / v.Length) * (sum / v.Length);
            return var;
        }
        private int rowCount = 0;
        private void strWrite_zyr(string str, string filePath, string fileName)
        {

            if (!Directory.Exists(filePath))
                Directory.CreateDirectory(filePath);
            if (!File.Exists(filePath + "\\" + fileName))
                File.Create(filePath + "\\" + fileName).Close(); //.Close 很关键,不然会有问题
            if (rowCount < 3600)
            {
                StreamWriter sw = new StreamWriter(filePath + "\\" + fileName, true);//true 追加数据
                sw.WriteLine(str);
                sw.Close();
                rowCount++;
            }
            else
            {
                StreamWriter sw = new StreamWriter(filePath + "\\" + fileName, false);
                sw.WriteLine(str);
                sw.Close();
                rowCount = 0;
            }
        }
    }
}

类DataProcess.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ThzData;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Drawing;

using ThzDataProcess;
using System.Windows.Forms;


namespace BLL
{
    public class Command
    {
        public static void CommandUp(int frame)
        {
            //string sendString = null;//要发送的字符串 
            byte[] Data = new byte[8];
            switch (frame)
            {
                case 0:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 00, 16 };//停止
                    break;
                case 6:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 00, 32 };//6帧/s 启动
                    break;
                case 8:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 00, 48 };//仅上传AD值
                    //Data = new byte[] { 22, 144, 87, 235, 00, 00, 00, 33 };//8帧/s 启动
                    break;
                case 10:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 00, 34 };//10帧/s 启动
                    break;
                case 12:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 00, 35 };//12帧/s 启动
                    break;
                case -1:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 00, 48 };//仅上传AD值
                    break;
                default:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 00, 33 };//8帧/s 启动
                    break;
            }
            UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 9001));
            //广播发送指令
            IPAddress remoteIP = IPAddress.Parse("255.255.255.255");
            int remotePort = 8010;
            //实例化广播
            IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort);

            //sendString = Console.ReadLine();
            //sendData = Encoding.Default.GetBytes(sendString);

            //client = new UdpClient();
            //将数据发送到远程端点 
            client.Send(Data, Data.Length, remotePoint);
            //关闭连接
            client.Close();

        }

        public static void CommandUp_v1(int frame, byte tair = 00)                     //看不懂
        {
            //string sendString = null;//要发送的字符串 
            byte[] Data = new byte[8];
            switch (frame)
            {
                case 0:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 16, tair };//停止
                    break;
                case 6:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 32, tair };//6帧/s 启动
                    break;
                case 8:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 48, tair };//仅上传AD值
                    //Data = new byte[] { 22, 144, 87, 235, 00, 00, 33, tair };//8帧/s 启动
                    break;
                case 10:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 34, tair };//10帧/s 启动
                    break;
                case 12:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 35, tair };//12帧/s 启动
                    break;
                case 1:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 97, tair };//自动获取编码器值范围
                    break;
                case 60:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 80, tair };//6帧/s 校准参数
                    break;
                case 80:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 81, tair };//8帧/s 校准参数
                    break;
                case 100:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 82, tair };//10帧/s 校准参数
                    break;
                case 120:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 83, tair };//12帧/s 校准参数
                    break;
                case -1:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 48, tair };//仅上传AD值
                    break;
                case 128:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 128, tair };//仅上传AD值
                    break;
                default:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 33, tair };//8帧/s 启动
                    break;
            }

            UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 9001));
           // IPAddress remoteIP = IPAddress.Parse("255.255.255.255");  //以广播方式发送
            IPAddress remoteIP = IPAddress.Parse("192.168.1.255");
            int remotePort = 8008;
            IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort);



            //sendString = Console.ReadLine();
            //sendData = Encoding.Default.GetBytes(sendString);

            //client = new UdpClient();
            //将数据发送到远程端点 
            client.Send(Data, Data.Length, remotePoint);
            //关闭连接
            client.Close();
            

        }

        public static void CommandUp_v2(int frame)
        {
            //string sendString = null;//要发送的字符串 
            byte[] Data = new byte[8];

            switch (frame)
            {
                case 41:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 65, 00 };//停止
                    break;
                case 42:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 66, 00 };//6帧/s 启动
                    break;
                case 43:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 67, 00 };//8帧/s 启动
                    break;
                default:
                    Data = new byte[] { 22, 144, 87, 235, 00, 00, 66, 00 };//8帧/s 启动
                    break;
            }

            UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 9001));
            //广播发送指令
            IPAddress remoteIP = IPAddress.Parse("255.255.255.255");
            int remotePort = 8008;
            //实例化广播
            IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort);

            //sendString = Console.ReadLine();
            //sendData = Encoding.Default.GetBytes(sendString);

            //client = new UdpClient();
            //将数据发送到远程端点 
            client.Send(Data, Data.Length, remotePoint);
            //关闭连接
            client.Close();

        }
    }

    public class DataProcess
    {
        string deviceIp = "";                                       //太赫兹设备IP
        const int devicePort = 8008;                                //太赫兹设备发送端口
        int localPort = new int();                                  //本机接收端口

        Queue<List<Byte[]>> DataQueue = new Queue<List<Byte[]>>();  //数据缓存队列
        Semaphore TaskSemaphore = new Semaphore(0, 2560);           //数据缓存队列缓存区
        object ThreadLock = new object();                           //线程锁

        public Action<Bitmap, string[], double[], bool, bool> ShowEvent;
        public Action<string, string, string, int> ShowEvent_zyr1;
        public Action<double, int> ShowEvent_zyr2;
       // public Action<int,Double> ShowEvent_zyr3;
        //MainForm mf = new MainForm();


        DataCalculate dc = new DataCalculate();


        #region 线程开启
        /// <summary>
        /// 所有线程开启函数
        /// </summary>
        public void Start()
        {
            StartAllThread();
        }

        /// <summary>
        /// 开启子线程
        /// </summary>
        private void StartAllThread()
        {
            StartDataRevThread();
            StartDataProcessThread();
            StartShowThread();
        }

        private void StartShowThread()
        {
            Thread t = new Thread(new ThreadStart(ShowAllVariables));                  //开启DataRevThread
            t.Name = "ShowAllVariables";                                            //线程名字
            t.Start();
            t.IsBackground = true;
        }

        /// <summary>
        /// 开启数据接收线程
        /// </summary>
        private void StartDataRevThread()
        {

            Thread t = new Thread(new ThreadStart(DataRevThread));                  //开启DataRevThread
            t.Name = "DataRevThread";                                            //线程名字
            t.Start();
            t.IsBackground = true;                                                  //后台运行
        }

        /// <summary>
        /// 数据处理线程开启
        /// </summary>
        private void StartDataProcessThread()
        {
            Thread t = new Thread(new ThreadStart(DataDecodeImageProcessThread));  //开启DataDecode_ImageProcessThread
            t.Name = "DataDecode_ImageProcessThread";                                            //线程名字
            t.Start();
            t.IsBackground = true;                                                  //后台运行
        }
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        public DataProcess(string deviceip, int localport)
        {
            deviceIp = deviceip;//192.168.1.120
            localPort = localport;//8008
        }


        /*Thread t = new Thread(Start);
           t.Priority = ThreadPriority.Highest;
           t.Start();*/

        #region 数据接收线程
        /// <summary>
        /// 数据接收线程
        /// </summary>
        private void DataRevThread()
        {
            
            try
            {
                //IPAddress remoteIP = IPAddress.Parse("255.255.255.255");                                      //广播


                UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Parse("192.168.1.119"), localPort));   //本机端口 一般UdpClient client = new UdpClient();
                IPAddress remoteIP = IPAddress.Parse(deviceIp);                                                   //远程IP
                int remotePort = devicePort;                                                                   //远程端口
                IPEndPoint endpoint = new IPEndPoint(remoteIP, remotePort);                                 //远程IP和端口
                client.Client.ReceiveBufferSize = 40960;//40960 默认值是8192
                //ARP触发
                client.Send(new byte[] { 00, 11 }, 2, endpoint);   //发送 00 ,11有何作用??



                while (true)
                    {
                      // MainForm f1 = new MainForm();
                      //f1.ShowThread("123");
                      List<Byte[]> Taskbuff = new List<Byte[]>();
                          for (int i = 0; i < 25; i++)                             //为什么是21?
                        {

                            Byte[] recv = client.Receive(ref endpoint);
                            // MainForm f1 = new MainForm();
                            // f1.ShowThread();
                            Taskbuff.Add(recv);


                       
                        DataShow_v1(recv, Environment.CurrentDirectory + "\\bin", "mydata.bin");



                        // writerFile(recv, Environment.CurrentDirectory + "\\bin\\mydata.bin");

                    }
                    // 任务队列为临界资源,需要锁 
                    lock (ThreadLock)
                        {
                            DataQueue.Enqueue(Taskbuff); //Queue<List<Byte[]>> DataQueue = new Queue<List<Byte[]>>();  在队列的末端添加元素

                        }
                        // 每添加一个任务,信号量加1
                        TaskSemaphore.Release(1);

                        //ChangeProducerText(String.Format("Consumer 1 take Task {0}\r\n", a));


                    }
                

                //client.Close();
            }
            catch (Exception ex)
            {
                string fileName = "Log\\debug" + localPort + "_DataDecode.txt";
                string content = DateTime.Now.ToLocalTime() + ex.Message + "\n" + ex.StackTrace + "\r\n";
                Logger(fileName, content);
            }

        }
        #endregion


        #region 数据显示
        private void DataShow_v1(Byte[] recv,string filePath,string fileName)
        {
            if (!Directory.Exists(filePath))
                Directory.CreateDirectory(filePath);
            if (!File.Exists(filePath+ "\\"+fileName))
                File.Create(filePath + "\\"+fileName).Close(); //.Close 很关键,不然会有问题
            FileStream fs = new FileStream(filePath + "\\"+fileName, FileMode.Append, FileAccess.Write);
            fs.Write(recv, 0, recv.Length);
            fs.Close();
            fs.Dispose();
        }
            private void DataShow(Byte[] recv)
        {
            //MainForm f1 = new MainForm();
            // ShowMessage(f1.richTextBox1, "开始显示数据");
            //  MainForm f1 = new MainForm();
            //f1.ShowThread("123");
            /*  int nLength = recv.Length;//字节数组长度
              string sByte = "";
              if (nLength > 0)
              {
                  sByte = Convert.ToString(recv[0], 16);//转换成16进制
                  if (nLength > 1)
                  {
                      for (int k = 1; k < recv.Length; k++)
                      {
                          sByte += ",";//用逗号隔开
                          sByte += Convert.ToString(recv[k], 16);//转换成16进制

                      }
                  }
              }
              if (!Directory.Exists(Environment.CurrentDirectory + "\\bin"))
                  Directory.CreateDirectory(Environment.CurrentDirectory + "\\bin");

              //Environment.CurrentDirectory + "\\" + DateTime.Now.ToString("HHmmssfff") + "bin.txt"
              // writerFile(strToToHexByte(sNeed.ToString().Substring(0)), "ZHEN\\Port" + localPort + "_Frame" + (CountNum) % 10000 + ".bin");
              using (StreamWriter file = new StreamWriter(Environment.CurrentDirectory + "\\bin\\" + DateTime.Now.ToString("HHmmss") + ".txt", true))
              {
                  file.WriteLine(sByte);
                  file.WriteLine("\r\n");

              }*/

            //if (!Directory.Exists(Environment.CurrentDirectory + "\\bin"))
            //    Directory.CreateDirectory(Environment.CurrentDirectory + "\\bin");

            //Stream flstr = new FileStream(Path.GetDirectoryName(Application.ExecutablePath))
            // BinaryWriter sw = new  BinaryWriter(new FileStream(Environment.CurrentDirectory + "\\bin\\mydata.bin", FileMode.Append, FileAccess.ReadWrite)); //创建文件  bin目录下
            //  sw.Write(recv);
            //  sw.Close();

            //writerFile(recv, Environment.CurrentDirectory + "\\bin\\mydata.bin");
            int nLength = recv.Length;//字节数组长度
             string sByte = "";
             if (nLength > 0)
             {
                 sByte = Convert.ToString(recv[0], 16);//转换成16进制
                 if (nLength > 1)
                 {
                     for (int i = 1; i < recv.Length; i++)
                     {
                         sByte += ",";//用逗号隔开
                         sByte += Convert.ToString(recv[i], 16);//转换成16进制

                     }
                 }
             }
            if (!File.Exists(Environment.CurrentDirectory +"\\bin.txt"))
                File.Create(Environment.CurrentDirectory + "\\bin.txt");
            //Environment.CurrentDirectory + "\\" + DateTime.Now.ToString("HHmmssfff") + "bin.txt"
            using (StreamWriter file = new StreamWriter(Environment.CurrentDirectory + "\\bin.txt", true))
            {
                file.WriteLine(DateTime.Now.ToString("HHmmssfff")+sByte);

            }

            //File.WriteAllBytes(Environment.CurrentDirectory+"bin.txt", recv);
            //ShowMessage(f1.richTextBox1, sByte);

        }
        // 向RichTextBox中添加文本
        delegate void ShowMessageDelegate(RichTextBox txtbox, string message);
        private void ShowMessage(RichTextBox txtbox, string message)
        {
            if (txtbox.InvokeRequired)
            {
                ShowMessageDelegate showMessageDelegate = ShowMessage;
                txtbox.Invoke(showMessageDelegate, new object[] { txtbox, message });
            }
            else
            {
                txtbox.Text += message + "\r\n";
            }
        }
        #endregion

        #region 数据解码图像处理线程
        private int CountNum = 0;
        //private int ErrorNum = 0;
        public bool getMeanMatFlag;
        //private string WenduC = "";
        //private string str2 = "";
        Stopwatch elapsetime = new Stopwatch();


        /// <summary>
        /// 数据解码图像处理
        /// </summary>
        private void DataDecodeImageProcessThread()
        {
            try
            {
                List<Byte[]> GetTask = new List<Byte[]>();  //数据缓存队列
                List<Byte[]> listBuff = new List<Byte[]>(); //多余数据缓存区
                THZData thzdata = new THZData();               //Thz数据

                while (true)
                {
                    //接收数据
                    TaskSemaphore.WaitOne();                //等待接收队列


                    lock (ThreadLock)                       //锁线程  
                    {
                        GetTask = DataQueue.Dequeue();   //Queue<List<Byte[]>> DataQueue = new Queue<List<Byte[]>>();
                    }

                    string[] duration = new string[3] { "", "", "" };
                    elapsetime.Restart();//计时开始
                    //数据解析解码
                    //DataDecode(GetTask, ref listBuff, ref thzdata);
                    

                    DataDecode_v1(GetTask, ref listBuff, ref thzdata);
                    //Console.WriteLine("123");


                    elapsetime.Stop();//计时结束
                    duration[0] = elapsetime.ElapsedMilliseconds.ToString("000");
                    //背景校准
                    //if (getMeanMatFlag)
                    //{
                    //    if (frame.UserData != null)
                    //        MeanMatList.Add(frame);

                    //    if (MeanMatList.Count == 10)
                    //    {
                    //        MeanMat = getMeanMat(MeanMatList);
                    //        MeanMatList.Clear();
                    //        getMeanMatFlag = false;
                    //    }
                    //    ImageClass.MeanMat = MeanMat;
                    //}
                    elapsetime.Restart();//计时开始


                    thzdata.StartImageProcess();
                    if (thzdata.FilterImage != null)   ///FilterImage滤波后图像
                    {
                        if (!Directory.Exists("ZHEN"))
                            Directory.CreateDirectory("ZHEN");

                        thzdata.FilterImage.Mat.Bitmap.Save("ZHEN\\" + DateTime.Now.ToString("HHmmssfff") + ".bmp");
                    }

                    elapsetime.Stop();//计时结束
                    duration[1] = elapsetime.ElapsedMilliseconds.ToString("0000");
                    duration[2] = (Convert.ToInt32(duration[0]) + Convert.ToInt32(duration[1])).ToString("0000");
                    //温度显示
                    double[] temparture = thzdata.GetTemparture();
                    if (thzdata.FinalImage != null)
                    {
                        ShowData SD = new ShowData(thzdata.FinalImage.Bitmap, temparture, duration, thzdata.isPeople, thzdata.isHidden);//thzdata.isPeople

                        // 任务队列为临界资源,需要锁 
                        lock (ThreadLock1)
                        {
                            ShowQueue.Enqueue(SD);

                        }
                        // 每添加一个任务,信号量加1
                        TaskSemaphore1.Release(1);
                    }
                    //if (ShowEvent != null && thzdata.FinalImage != null)
                    //    ShowEvent(thzdata.FinalImage.Bitmap, duration, Temparture, thzdata.isPeople);
                    //ShowEvent(PB1Image, ImageClass.lImage, ImageClass.isPeople, elapsetime.ElapsedMilliseconds.ToString(), ImageClass.HideGoods, "错帧数:" + ErrorNum);
                    //ShowTextEvent.Invoke(ImageClass.OutArray.Bitmap);


                }
            }
            catch (Exception ex)
            {
                string fileName = "Log\\debug" + localPort + "_DataDecode.txt";
                string content = DateTime.Now.ToLocalTime() + ex.Message + "\n" + ex.StackTrace + "\r\n";
                Logger(fileName, content);
            }

        }

        Queue<ShowData> ShowQueue = new Queue<ShowData>();  //数据缓存队列
        Semaphore TaskSemaphore1 = new Semaphore(0, 2560);  //数据缓存队列缓存区 
                                                           //第一个就是信号量的内部整数初始值,也就是初始请求数,第二个参数就是最大请求数。

        object ThreadLock1 = new object();
        private void ShowAllVariables()
        {
            ShowData GetTask = new ShowData();  //数据缓存队列
            while (true)
            {
                //接收数据
                TaskSemaphore1.WaitOne();                //等待接收队列
                lock (ThreadLock1)                       //锁线程  
                {
                    GetTask = ShowQueue.Dequeue();
                }

                if (GetTask.ThzImage != null)
                {
                    if (!Directory.Exists("ZHEN"))
                        Directory.CreateDirectory("ZHEN");


                }

                if (ShowEvent != null && GetTask.ThzImage != null)
                    ShowEvent(GetTask.ThzImage, GetTask.Duration, GetTask.Temparture, GetTask.IsPeople, GetTask.IsHidden);

            }
        }

        public void Correct()
        {
            THZData.Recorrect = true;
        }

        //public void SetMirror(bool mirrorFlag)
        //{
        //    thzdata.MirrirFlag = mirrorFlag;
        //}
        #endregion

        /// <summary>
        /// 数据解码
        /// </summary>
        /// <param name="GetTask">List</param>
        /// <param name="listBuff">List</param>
        /// <param name="frame">输出PartData</param>
        /// <param name="FrameLength">FrameLength</param>
        /// <param name="PackageNum">PackageNum</param>
        void DataDecode(List<Byte[]> GetTask, ref List<Byte[]> listBuff, ref THZData frame)
        {
            int PackageNum = 25;
            //if (listBuff.Count >= 100)
            //{
            //    listBuff.Clear();
            //    return;
            //}
            //排除异常项
            listBuff.RemoveAll(s => s.Count() < 1000);

            StringBuilder sNeed = new StringBuilder();

            GetTask.AddRange(listBuff);
            listBuff.Clear();

            foreach (var item in GetTask.OrderBy(s => 256 * s[6] + s[7]).GroupBy(s => 256 * 256 * 256 * s[2] + 256 * 256 * s[3] + 256 * s[4] + s[5]))
            {
                //PackageNum = 256 * item.ToList()[0][0] + item.ToList()[0][1];
                if (item.Count() == PackageNum)
                {

                    var Zhendata = item.OrderBy(s => s[6] * 256 + s[7]).ToList();

                    if (Zhendata[0].Count() != 1420)
                        continue;

                    foreach (Byte[] match in Zhendata)
                        sNeed.Append(BitConverter.ToString(match).Replace("-", "").Substring(20).ToUpper());
                    //if (!Directory.Exists("ZHEN"))
                    //    Directory.CreateDirectory("ZHEN");
                    //writerFile(strToToHexByte(sNeed.ToString().Substring(0)), "ZHEN\\Port" + localPort + "_Frame" + (CountNum) % 10000 + ".bin");
                    CountNum++;
                    frame.Init(sNeed.ToString());//???
                    //DecodeFrame(sNeed, ref frame, indexHead, indexTair); 

                    sNeed.Clear();
                }
                else
                {
                    listBuff.AddRange(item.ToList());
                }
            }

        }
        /// <summary>
        /// 数据解码
        /// </summary>
        /// <param name="GetTask">List</param>
        /// <param name="listBuff">List</param>
        /// <param name="frame">输出PartData</param>
        /// <param name="FrameLength">FrameLength</param>
        /// <param name="PackageNum">PackageNum</param>
        void DataDecode_v1(List<Byte[]> GetTask, ref List<Byte[]> listBuff, ref THZData frame)   //ref作用?
        {
            int PackageNum = 25;
            //if (listBuff.Count >= 100)
            //{
            //    listBuff.Clear();
            //    return;
            //}
            //排除异常项
            listBuff.RemoveAll(s => s.Count() < 1000);

            StringBuilder sNeed = new StringBuilder();

            GetTask.AddRange(listBuff);
            listBuff.Clear();
           

            foreach (var item in GetTask.OrderBy(s => 256 * s[6] + s[7]).GroupBy(s => 256 * 256 * 256 * s[2] + 256 * 256 * s[3] + 256 * s[4] + s[5])) //按照包排序、按照帧分组,每次取出一帧
            {

                PackageNum = 256 * item.ToList()[0][0] + item.ToList()[0][1];//获取一帧前两个字节的值,即单帧包数
                if (item.Count() == PackageNum)//如果一帧的包数量和PackageNum相等则是一个完整的包
                {

                    var Zhendata = item.OrderBy(s => s[6] * 256 + s[7]).ToList();//一帧数据按照包排序后存放到Zhendata

                    if (Zhendata[0].Count() != 1420)//第一包不是1420则退出
                        continue;

                    //dc.tempartureData_zyr(Zhendata, ShowEvent_zyr2);
                    dc.adDataCaculate_zyr(Zhendata, ShowEvent_zyr1,ShowEvent_zyr2);

                    foreach (Byte[] match in Zhendata)  //每次取出一个包也就是1420字节,取一帧的数据
                        sNeed.Append(BitConverter.ToString(match).Replace("-", "").Substring(20).ToUpper());
                    //if (!Directory.Exists("ZHEN"))
                    //    Directory.CreateDirectory("ZHEN");
                    writerFile(strToToHexByte(sNeed.ToString().Substring(0)), "ZHEN\\Port" + localPort + "_Frame" + (CountNum) % 10000 + ".bin");
                    CountNum++;
                    frame.Init(sNeed.ToString());
                    //DecodeFrame(sNeed, ref frame, indexHead, indexTair); 

                    sNeed.Clear();
                }
                else
                {
                    listBuff.AddRange(item.ToList());
                }
            }

        }
        void DataDecode_v2(List<Byte[]> GetTask, ref List<Byte[]> listBuff, ref THZData frame)
        {
            int PackageNum = 25;
            //int ChannelCount = 36;
            //int SampleCount = 473;
     
            listBuff.RemoveAll(s => s.Count() < 1000);

            StringBuilder sNeed = new StringBuilder();

            GetTask.AddRange(listBuff);
            listBuff.Clear();

            foreach (var item in GetTask.OrderBy(s => 256 * s[6] + s[7]).GroupBy(s => 256 * 256 * 256 * s[2] + 256 * 256 * s[3] + 256 * s[4] + s[5])) //按照包排序、按照帧分组
            {
                PackageNum = 256 * item.ToList()[0][0] + item.ToList()[0][1];
                if (item.Count() == PackageNum)
                {

                    var Zhendata = item.OrderBy(s => s[6] * 256 + s[7]).ToList();

                    if (Zhendata[0].Count() != 1420)
                        continue;

                    /*mycode*/
                    /* List<Byte> frameByteData = new List<Byte>();
                     double[] ChannelData = new double[438] ;
                     double avg = 0, Variance;
                     foreach (Byte[] Package in Zhendata)
                         foreach (Byte byt in Package)
                             frameByteData.Add(byt);
                     MessageBox.Show(frameByteData.Count().ToString());
                     ChannelCount = 256 * item.ToList()[0][26] + item.ToList()[0][27];
                     SampleCount = 256 * item.ToList()[0][28] + item.ToList()[0][29];
                     for (int i = 0; i < ChannelCount; i++)    // 36
                     {
                         for (int j = 0; j < SampleCount; j++)  // 438
                             ChannelData[j]= frameByteData[j * 74 + 51+i] * 256 + frameByteData[j * 74 + 52+i];
                         avg = Var(ChannelData);
                         Variance=ChannelData.Average();
                         strWrite(ChannelData+"--"+avg+"--"+Variance, Environment.CurrentDirectory + "\\bin","ad.txt");

                     }*/

                    


                    foreach (Byte[] match in Zhendata)
                        sNeed.Append(BitConverter.ToString(match).Replace("-", "").Substring(20).ToUpper());

                    strToToHexByte(sNeed.ToString().Substring(0));


                    //if (!Directory.Exists("ZHEN"))
                    //    Directory.CreateDirectory("ZHEN");
                    writerFile(strToToHexByte(sNeed.ToString().Substring(0)), "ZHEN\\Port" + localPort + "_Frame" + (CountNum) % 10000 + ".bin");
                    CountNum++;
                    frame.Init(sNeed.ToString());
                    //DecodeFrame(sNeed, ref frame, indexHead, indexTair); 

                    sNeed.Clear();
                }
                else
                {
                    listBuff.AddRange(item.ToList());
                }
            }

        }


        /* public void callBack_zyr1(int row, int column, string str)
         {

            ShowEvent_zyr1(row, column, str);
          }
     public void callBack_zyr2(string str)
     {

         ShowEvent_zyr2(str);
     }*/
        #region mycode_zyr
        // DataProcess dp = null;
        //public void tempartureData_zyr(List<byte[]> Zhendata)
        //{
        //    StringBuilder sNeed = new StringBuilder();

        //    foreach (Byte[] match in Zhendata)
        //        sNeed.Append(BitConverter.ToString(match).Replace("-", "").Substring(20).ToUpper());
        //    double[] temparture = GetTemparture_zyr(sNeed.ToString());
        //    // mf.ShowlbDevTem(string.Format("设备温度:\nT1:{0:N}°\nT2:{1:N}°\nT3:{2:N}°\nT4:{3:N}°", temparture[0], temparture[1], temparture[2], temparture[3]));
        //    ShowEvent_zyr2(string.Format("设备温度:\nT1:{0:N}°\nT2:{1:N}°\nT3:{2:N}°\nT4:{3:N}°", temparture[0], temparture[1], temparture[2], temparture[3]));
        //   // dp.callBack_zyr2(string.Format("设备温度:\nT1:{0:N}°\nT2:{1:N}°\nT3:{2:N}°\nT4:{3:N}°", temparture[0], temparture[1], temparture[2], temparture[3]));
        //    sNeed.Clear();
        //    foreach (var tem in temparture)
        //        sNeed.Append(tem + "***");
        //    strWrite_zyr(sNeed.ToString(), Environment.CurrentDirectory + "\\bin", "tempartureData.txt");
        //    sNeed.Clear();


        //}

        public double[] GetTemparture_zyr(string str)
        {
            string tepStr = str.Substring(20 * 2, 8 * 2);
            double[] Temparture = new double[4];
            if (tepStr == null)
                return Temparture;
            byte[] Wen = DataProcess.strToToHexByte(tepStr);
            if ((Wen[0] & 0xf0) >> 4 == 15)
                Temparture[0] = -(~Wen[1] + 1 + 256.0 * ~Wen[0]) / 16;
            else
                Temparture[0] = (Wen[1] + 256.0 * Wen[0]) / 16;

            if ((Wen[2] & 0xf0) >> 4 == 15)
                Temparture[1] = -(~Wen[3] + 1 + 256.0 * ~Wen[2]) / 16;
            else
                Temparture[1] = (Wen[3] + 256.0 * Wen[2]) / 16;

            if ((Wen[4] & 0xf0) >> 4 == 15)
                Temparture[2] = -(~Wen[5] + 1 + 256.0 * ~Wen[4]) / 16;
            else
                Temparture[2] = (Wen[5] + 256.0 * Wen[4]) / 16;

            if ((Wen[6] & 0xf0) >> 4 == 15)
                Temparture[3] = -(~Wen[7] + 1 + 256.0 * ~Wen[6]) / 16;
            else
                Temparture[3] = (Wen[7] + 256.0 * Wen[6]) / 16;
            return Temparture;
        }
        int zhenRows = 0;
       /* public void adDataCaculate_zyr(List<byte[]> Zhendata)
        {
            byte[] byteData = new byte[35250];//1410*25
            int count1 = 0, count2 = 0;
            StringBuilder sNeed = new StringBuilder();
            MainForm mf = new MainForm();

            foreach (Byte[] Package in Zhendata)
            {
                count1 = 0;
                foreach (byte byt in Package)
                {
                    if (count1 >= 20)   //跳过第一个数
                    {

                        byteData[count2] = byt;
                        count2++;

                    }
                    count1++;
                }
            }
            // Console.ReadKey();
            double[] channel = new double[473];
            double variance = 0.0, average = 0.0;
            for (int i = 0; i < 36; i++)
            {
                for (int j = 0; j < 473; j++)
                {
                    byte bigByte = Convert.ToByte(byteData[j * 74 + i * 2].ToString("X"), 16);
                    if ((bigByte & 0xf0) >> 4 == 15)
                        channel[j] = -(~byteData[j * 74 + i * 2 + 30] + 1 + 256.0 * ~byteData[j * 74 + i * 2 + 31]) / 8192.0 * 10.0;//2^12 =4096
                    else
                        channel[j] = (byteData[j * 74 + i * 2 + 30] + 256.0 * ~byteData[j * 74 + i * 2 + 31]) / 8192.0 * 10.0;
                    sNeed.Append(channel[j] + ",");
                }
                variance = Var_zyr(channel);
                //mf.dataShow(zhenRows, 2 * i + 1, variance.ToString());
                ShowEvent_zyr1(zhenRows, 2 * i + 1, variance.ToString());
                //dp.callBack_zyr1(zhenRows, 2 * i + 1, variance.ToString());
                sNeed.Append("***variance:" + variance + "***average:");
                average = channel.Average();
                // mf.dataShow(zhenRows, 2 * i , average.ToString());
                 ShowEvent_zyr1(zhenRows, 2 * i, average.ToString());
                //dp.callBack_zyr1(zhenRows, 2 * i, average.ToString());
                sNeed.Append(average);
                strWrite_zyr(sNeed.ToString(), Environment.CurrentDirectory + "\\bin", "channelData.txt");
                sNeed.Clear();
            }
            zhenRows++;
        }*/

        public double Var_zyr(double[] v)
        {
            double sum1 = 0;
            for (int i = 0; i < v.Length; i++)
            {
                double temp = v[i] * v[i];
                sum1 = sum1 + temp;
            }

            double sum = 0;
            foreach (double d in v)
            {
                sum = sum + d;
            }
            double var = sum1 / v.Length - (sum / v.Length) * (sum / v.Length);
            return var;
        }
        private int rowCount = 0;
        private void strWrite_zyr(string str, string filePath, string fileName)
        {

            if (!Directory.Exists(filePath))
                Directory.CreateDirectory(filePath);
            if (!File.Exists(filePath + "\\" + fileName))
                File.Create(filePath + "\\" + fileName).Close(); //.Close 很关键,不然会有问题
            if (rowCount < 3600)
            {
                StreamWriter sw = new StreamWriter(filePath + "\\" + fileName, true);//true 追加数据
                sw.WriteLine(str);
                sw.Close();
                rowCount++;
            }
            else
            {
                StreamWriter sw = new StreamWriter(filePath + "\\" + fileName, false);
                sw.WriteLine(str);
                sw.Close();
                rowCount = 0;
            }
        }
        #endregion 
        private void strWrite(string str, string filePath, string fileName)
        {
            if (!Directory.Exists(filePath))
                Directory.CreateDirectory(filePath);
            if (!File.Exists(filePath + "\\" + fileName))
                File.Create(filePath + "\\" + fileName).Close(); //.Close 很关键,不然会有问题

            //方法一
            StreamWriter sw = new StreamWriter(filePath + "\\" + fileName, true);
            sw.WriteLine(str);
            sw.Close();

            //方法2
           /* string path = "D\1.txt";//文件的路径,保证文件存在。
            FileStream fs = new FileStream(path, FileMode.Append);
            SteamWriter sw = new StreamWriter(fs);
            sw.WriteLine(要追加的内容);
            sw.Close();
            fs.Close();*/
        }

       
        /// <summary>
        /// 字符串转16进制Byte字节
        /// </summary>
        /// <param name="hexString">输入字符串</param>
        /// <returns>转化的Byte字节</returns>
        public static byte[] strToToHexByte(string hexString)
        {
            hexString = hexString.Replace("-", "");
            if ((hexString.Length % 2) != 0)
                hexString += "20";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

        /// <summary>
        /// 帧数据读取,存放
        /// </summary>
        /// <param name="array">帧数据数组</param>
        /// <param name="strPath">存放文件</param>
        private void writerFile(byte[] array, string strPath)
        {
            //string content = this.txtContent.Text.ToString();

            if (string.IsNullOrEmpty(strPath))
            {
                return;
            }

            //将string转为byte数组
            //byte[] array = Encoding.UTF8.GetBytes(content);

            //string path = Server.MapPath("/test.txt");
            //创建一个文件流
            FileStream fs = new FileStream(strPath, FileMode.Create);

            //将byte数组写入文件中
            fs.Write(array, 0, array.Length);
            //所有流类型都要关闭流,否则会出现内存泄露问题
            fs.Close();
            //Response.Write("保存文件成功");
        }

        private void Logger(string fileName, string content)
        {
            //StreamWriter sw = new StreamWriter(fileName, true);
            //sw.Write(content);
           // sw.Close(); sw.Dispose();

        }
    }

    class ShowData
    {
        public Bitmap ThzImage;
        public string[] Duration;
        public double[] Temparture;
        public bool IsPeople;
        public bool IsHidden;
        public ShowData() { }
        public ShowData(Bitmap bitmap, double[] temparture, string[] duration, bool peopleFlag, bool hidFlag)
        {
            ThzImage = bitmap;
            IsPeople = peopleFlag;
            IsHidden = hidFlag;
            Duration = duration;
            Temparture = temparture;
        }
    }
}

类THZData.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using Emgu.Util;
using System.Drawing;
using System.Threading.Tasks;

namespace ThzData
{
    public class THZData
    {
        private FrameMsg frameMsg;
        private Byte[] frameData;
        private int frameLength;
        private int ImageHeight;
        private int oriImageWidth;

        public bool isPeople;                   //人物判断
        public bool isHidden;
        private Matrix<int> backgroundframe;    //判定中间背景帧
        private List<Matrix<double>> multiImageList;//多帧平均列表
        public Matrix<double> PreProcessImage;  //预处理后图像
        public Matrix<byte> AlignImage;         //校准后图像
        public Matrix<int> MeanMat;             //输入的背景均值矩阵
        public Matrix<byte> FilterImage;        //滤波后图像
        public Mat FinalImage;                  //最终图像
        //public Dictionary<Rectangle, string> dictRects;//可疑块目标框架
        //public Dictionary<Mat, Rectangle> dictCoutours;//可疑轮廓内部信息
        public List<Rectangle> listRects;
        public bool MirrirFlag;
        public static bool Recorrect = false;
        int count = 0;

        const int JBianNum = 13;
        const int iHumanThreshold = 35;
        const int resizeImageWidth = 183;


        public THZData()
        {
            this.frameMsg = new FrameMsg();
            this.isPeople = false;
            this.isHidden = false;
            this.multiImageList = new List<Matrix<double>>();

        }

        public void Init(string allMsg)
        {
            if (allMsg.Count() > 0 && frameMsg != null)
            {
                //this.frameMsg.Init(allMsg.Substring(8, 36 * 2));
                this.frameMsg.Init_v1(allMsg.Substring(8, 36 * 2));
                this.ImageHeight = Convert.ToInt32(frameMsg.SampNum, 16); //BitConverter.ToInt32(Encoding.Default.GetBytes(frameMsg.SampNum), 0);
                this.oriImageWidth = Convert.ToInt32(frameMsg.ChannelNum, 16);//16进制str转int
                this.frameLength = Convert.ToInt32(frameMsg.DataLength, 16);// BitConverter.ToInt32(Encoding.Default.GetBytes(frameMsg.DataLength), 0);
                this.frameData = strToToHexByte(allMsg.Substring(80, frameLength * 2));//frameLength,28860

                if (MeanMat == null)
                    this.MeanMat = new Matrix<int>(new Size(1, ImageHeight * oriImageWidth));

                this.backgroundframe = new Matrix<int>(new Size(1, ImageHeight * oriImageWidth));
                this.PreProcessImage = new Matrix<double>(new Size(1, (ImageHeight - JBianNum) * oriImageWidth));
                this.AlignImage = new Matrix<byte>(new Size(resizeImageWidth * 2, (ImageHeight - JBianNum) * 2));
                this.FinalImage = new Mat();
                this.FilterImage = new Matrix<byte>(new Size(resizeImageWidth * 2, (ImageHeight - JBianNum) * 2));
                //this.dictRects = new Dictionary<Rectangle, string>();
                //this.dictCoutours = new Dictionary<Mat, Rectangle>();
                this.listRects = new List<Rectangle>();

            }
        }

        /// <summary>
        /// 开始处理数据
        /// </summary>
        /// <param name="frame">PartData</param>
        public void StartImageProcess()
        {
            if (this.frameData == null)
                return;

            this.isHidden = false;
            //获取畸变矫正后初始矩阵
            getInitMatrix();

            //加权归一化
            Normalization();

            if (isPeople)
            {
                //滤波,分割,识别
                Filter();
                Seg_Reg();
            }
            else
            {
                CvInvoke.CvtColor(AlignImage, this.FinalImage, ColorConversion.Gray2Bgr);//Outputtemp,BoxArray
            }
            //CvInvoke.CvtColor(AlignImage, this.FinalImage, ColorConversion.Gray2Bgr);//Outputtemp,BoxArray
        }

        /// <summary>
        /// 获取畸变矫正后初始矩阵
        /// </summary>
        /// <param name="Data">Matrix<Byte></param>
        private void getInitMatrix()
        {
            Matrix<Byte> Data = new Matrix<Byte>(this.frameData);    //Byte转Matrix
            //临时变量temp1,temp2和temp3
            int Height = this.ImageHeight;
            int Width = this.oriImageWidth;
            Matrix<int> temp1 = new Matrix<int>(new Size(1, Height * Width));
            Matrix<double> temp2 = new Matrix<double>(new Size(1, Height * Width));
            //Matrix<double> temp3 = new Matrix<double>(new Size(1, Height * Width));

            //获取矩阵,temp1
            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    //temp[i * n + j, 0] = (256 * msImg[i * 2 * (n + 1) + 2*j, 0] + msImg[i * 2 * (n + 1) + 2*j + 1, 0])/16;
                    temp1[i + j * Height, 0] = (256 * Data[i * 2 * (Width + 1) + 2 * j, 0] + Data[i * 2 * (Width + 1) + 2 * j + 1, 0]);
                }
            }

            //判断是否有人
            double MMMAX = 0;
            for (int j = 0; j < Width; j++)
            {
                Matrix<int> temptemp = new Matrix<int>(new Size(1, Height));
                for (int i = 0; i < Height; i++)
                {
                    temptemp[i, 0] = temp1[i + j * Height, 0];
                }
                //屏蔽某列
                //if (j == 35)
                //    continue;
                double Maxnum, Minnum;
                Point a, b;
                temptemp.MinMax(out Minnum, out Maxnum, out a, out b);

                MMMAX = (Maxnum - Minnum) > MMMAX ? (Maxnum - Minnum) : MMMAX;
            }
            isPeople = MMMAX > iHumanThreshold;                             //MMMax 行峰峰值

            //奇偶翻转,temp2
            if (this.frameMsg.Isodd)
            {
                for (int i = 0; i < Height; i++)
                {
                    for (int j = 0; j < Width; j++)
                    {
                        backgroundframe[j * Height + (Height - 1 - i), 0] = temp1[j * Height + i, 0];
                    }
                }
            }
            else
            {
                backgroundframe = temp1;
            }

            //背景校准
            if (!isPeople)
            {
                //自动背景校准
                MeanMat = MeanMat * 3 / 4 + backgroundframe / 4;
            }
            else if (Recorrect)
            {
                count++;
                //手动背景校准
                MeanMat = MeanMat * 3 / 4 + backgroundframe / 4;
                if (count > 15)
                    Recorrect = true;
            }

            //减背景均值,temp3
            //修改人 於景瞵 2018.6.1 列均值
            Matrix<double> MeanRow = new Matrix<double>(new Size(1, Width));
            for (int i = 0; i < Width; i++)
            {
                for (int j = 0; j < Height; j++)
                {
                    MeanRow[i, 0] += MeanMat[j + i * Height, 0];

                }
                MeanRow[i, 0] = MeanRow[i, 0] / Height;
            }
            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    temp2[i + j * Height, 0] = (backgroundframe[i + j * Height, 0] - MeanRow[j, 0]); // 通道均匀系数* Mean_p[j, 0];
                    //屏蔽某列
                    //if (j == 35) //j == 33 || j == 34 ||
                    //    temp2[i + j * Height, 0] = 0;
                }
            }
            //修改人 於景瞵 2018.6.1 点均值
            //for (int i = 0; i < Height; i++)
            //{
            //    for (int j = 0; j < Width; j++)
            //    {
            //        temp2[i + j * Height, 0] = (backgroundframe[i + j * Height, 0] - MeanMat[i + j * Height, 0]) * Mean_p[j, 0];
            //        //屏蔽某列
            //        //if (j == 35) //j == 33 || j == 34 ||
            //        //    temp2[i + j * Height, 0] = 0;
            //    }
            //}

            //奇偶抖动矫正
            //if (this.frameMsg.Isodd)
            //{
            //    for (int i = 0; i < Height; i++)
            //    {
            //        for (int j = 0; j < Width; j++)
            //        {
            //            temp3[j * (Height) + i, 0] = temp2[j * Height + i, 0];
            //        }
            //    }
            //}
            //else
            //{
            //    for (int i = 0; i < Height ; i++)
            //    {
            //        for (int j = 0; j < Width; j++)
            //        {
            //            temp3[j * (Height) + i, 0] = temp2[j * Height + i, 0];
            //        }
            //    }
            //}

            //畸变矫正InitMatrix


            for (int i = 0; i < (Height) - JBianNum; i++)
            {
                for (int j = 0; j < Width / 2; j++)
                {
                    //PreProcessImage = InitMatrix;
                    if (MirrirFlag)
                    {
                        PreProcessImage[(2 * j) * (Height - JBianNum) + i, 0] = temp2[(2 * j) * (Height) + (i + 0), 0];
                        PreProcessImage[(2 * j + 1) * (Height - JBianNum) + i, 0] = temp2[(2 * j + 1) * (Height) + (i + JBianNum), 0];
                    }
                    //镜像
                    else
                    {
                        PreProcessImage[(Width - 2 * j - 1) * (Height - JBianNum) + i, 0] = temp2[(2 * j) * (Height) + (i + 0), 0];
                        PreProcessImage[(Width - 2 * j - 2) * (Height - JBianNum) + i, 0] = temp2[(2 * j + 1) * (Height) + (i + JBianNum), 0];
                    }
                }
            }


        }

        /// <summary>
        /// 加权归一化,和插值
        /// </summary>
        private void Normalization()
        {
            int height = this.ImageHeight - JBianNum;     //矫正后图像高度
            int width = this.oriImageWidth;                          //可以屏蔽一些列


            Matrix<double> temp = new Matrix<double>(new Size(1, width * height));
            Matrix<Byte> temp2 = new Matrix<Byte>(new Size(width, height));
            //Matrix<Byte> temp3 = new Matrix<Byte>(new Size(183 * 2, height * 2));

            //加多帧平均算法
            multiImageList.Add(PreProcessImage);
            //加权系数
            double p1 = 0.0;
            double p2 = 0.0;
            double p3 = 1 - p1 - p2;
            if (multiImageList != null && multiImageList.Count > 3)
            {
                multiImageList.RemoveAt(0);
                temp = p1 * multiImageList[0] + p2 * multiImageList[1] + p3 * multiImageList[2];
            }
            else
            {
                temp = PreProcessImage;
            }

            //最大值最小值
            double Maxnum, Minnum;
            Point a, b;
            temp.MinMax(out Minnum, out Maxnum, out a, out b);
            //isPeople = (Maxnum - Minnum) > 70;

            //归一化
            if (isPeople)
            {
                //Parallel.For(0, height, i =>
                //{
                //    for (int j = 0; j < width; j++)
                //    {
                //        //temp2[i, j] = (Byte)(255 - (int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 0.75) * 255));
                //        //temp2[i, j] = (Byte)(int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 1.2) * 255);
                //        //镜像
                //        temp2[i, width - 1 - j] = (Byte)(int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 1.2) * 255);
                //        //CvInvoke.Normalize(temp2,temp2,255);
                //    }
                //});

                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {
                        //temp2[i, j] = (Byte)(255 - (int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 0.75) * 255));
                        //temp2[i, j] = (Byte)(int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 1.2) * 255);
                        //镜像
                        //temp2[i, width - 1 - j] = (Byte)(int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 1.2) * 255);
                        temp2[i, width - 1 - j] = (Byte)(int)((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum) * 255);

                    }
                }
                //CvInvoke.Normalize(temp, temp2,255);
            }
            else
            {
                //Parallel.For(0, height, i =>
                //{
                //    for (int j = 0; j < width; j++)
                //    {
                //        //temp2[i, j] = (Byte)(50 - (int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 0.75) * 50));
                //        //temp2[i, j] = (Byte)(int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 1.0) * 30);
                //        //镜像
                //        //temp2[i, width - 1 - j] = (Byte)(int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 1.0) * 30);
                //        CvInvoke.Normalize(temp2, temp2, 30);
                //    }
                //});

                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {
                        //temp2[i, j] = (Byte)(50 - (int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 0.75) * 50));
                        //temp2[i, j] = (Byte)(int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 1.0) * 30);
                        //镜像
                        //temp2[i, width - 1 - j] = (Byte)(int)(Math.Pow(((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum)), 1.0) * 30);
                        temp2[i, width - 1 - j] = (Byte)(int)((temp[i + j * height, 0] - Minnum) / (Maxnum - Minnum) * 30);

                    }
                }
                //CvInvoke.Normalize(temp, temp2);


            }

            //插值Resize
            CvInvoke.Resize(temp2, this.AlignImage, new Size(resizeImageWidth * 2, height * 2), 0, 0, Inter.Lanczos4);//183 * 2, height * 2

            //InitMiddleImage = temp3.Mat;
            //this.AlignImage = temp3;

        }

        /// <summary>
        /// filter滤波 
        /// </summary>
        private void Filter()
        {
            //isWarningImage = false;
            Matrix<byte> BoxArray = this.AlignImage.Clone();           //滤波矩阵
            //Mat MedianMat = InitMiddleImage.Clone();
            //Matrix<byte> MedianMat = this.AlignImage.Clone();
            //Mat Outputtemp = new Mat();
            //BoxArray._Mul(MedianMat);

            //中值滤波
            CvInvoke.MedianBlur(BoxArray, BoxArray, 9);
            //Boxfilter
            CvInvoke.BoxFilter(BoxArray, BoxArray, DepthType.Cv8U, new Size(9, 9), new Point(-1, -1), true, BorderType.Reflect101);
            //CvInvoke.FastNlMeansDenoising(MedianMat,BoxArray);

            //背景归0
            //Matrix<byte> tempArray = new Matrix<byte>(new Size(BoxArray.Width, BoxArray.Height));
            //CvInvoke.Threshold(BoxArray, tempArray, 100, 1, ThresholdType.Binary);
            //BoxArray._Mul(tempArray);

            //ACE图像增强
            BoxArray = ACE(BoxArray);
            //CvInvoke.MedianBlur(BoxArray, BoxArray, 9);
            CvInvoke.BoxFilter(BoxArray, BoxArray, DepthType.Cv8U, new Size(9, 9), new Point(-1, -1), true, BorderType.Reflect101);

            //输出图像为滤波后图像转三通道
            //CvInvoke.Threshold(BoxArray, Outputtemp, Th>50?Th:50, 255, ThresholdType.ToZero);
            CvInvoke.CvtColor(BoxArray, this.FinalImage, ColorConversion.Gray2Bgr);//Outputtemp,BoxArray
            this.FilterImage = BoxArray;
        }
        /// <summary>
        /// 自适应阈值分割 + 目标区域方块提取
        /// </summary>
        private void Seg_Reg()
        {
            ///分割
            //手动阈值

            double Th = graythresh(FilterImage.Mat.GetData());//* 1.10    

            //阈值分割矩阵
            //Matrix<byte> ThreArray = InitMiddleImage.Clone();
            //自动阈值分割。。。自适应阈值分割,使用工具包
            //CvInvoke.Threshold(BoxArray, ThreArray, 80, 1, ThresholdType.Otsu);
            //BoxArray._Mul(ThreArray);

            //手动阈值分割。。。手动阈值分割,自写函数
            //double Th = graythresh(BoxArray.Mat.GetData())*1.10;
            CvInvoke.Threshold(FilterImage, FilterImage, Th * 1.10, 255, ThresholdType.ToZero);//InputArray,BoxArray,ThresholdType.ToZero,ThresholdType.Binary

            ///识别            
            regCoutour();

            ///画图
            drawCoutours();
        }

        bool matchCoutours(Mat roi)
        {
            //中心区域为黑
            if (CvInvoke.Mean(roi).V0 > 60)
                return false;
            else
                return true;
        }

        void drawCoutours()
        {
            var color = new MCvScalar(0, 0, 255);
            //if (isPeople)
            {

                //if (CountNum % 3 == 0)  //修改人 於景瞵 2018.4.23   
                {
                    //if (rects != null && rects.Count != 0 && rects.Count <= 10)
                    if (listRects != null && listRects.Count != 0 && listRects.Count <= 10) //修改时间18.4.16
                    {
                        ////isWarningImage = true;
                        ////HideGoods = "到" + dictRects.Count + "个危险品";
                        //foreach (var rect in dictRects)
                        //{
                        //    if (rect.Value == "一类")
                        //    {
                        //        HideGoods = "到" + rect.Value + "危险品";
                        //        break;
                        //    }
                        //    HideGoods = "到" + rect.Value + "危险品";
                        //}
                    }
                }

                if (listRects.Count <= 10 && listRects.Count > 0)
                {
                    this.isHidden = true;
                    foreach (var rect in listRects)
                    {
                        //Mat roi = new Mat(rect,new Rectangle(new Point(rect.Value.Width/2-1,rect.Value.Height/2-1),new Size(3,3)));
                        //中心区域为黑
                        //if (CvInvoke.Mean(roi).V0 > 60)
                        //    continue;
                        //if (matchCoutours(roi))
                        {
                            CvInvoke.Rectangle(FinalImage, rect, color);
                            //CvInvoke.PutText(FinalImage, "Hidden", rect.Value.Location, FontFace.HersheyComplex, 0.4, color);
                        }
                    }
                }
                //CountNum++; //修改人 於景瞵 2018.4.23 
            }

        }

        /// <summary>
        /// 轮廓提取函数
        /// 20180416 修改人 於景瞵 
        /// </summary>
        /// <param name="srcimage"> 原始图像</param>
        /// <param name="OutImage"> 存放轮廓图像</param>
        /// <returns> 返回目标图像</returns>
        private void regCoutour()
        {
            Mat srcimage = this.FilterImage.Mat.Clone();
            Mat hierarchy = new Mat();
            Emgu.CV.Util.VectorOfVectorOfPoint Coutours = new Emgu.CV.Util.VectorOfVectorOfPoint();
            CvInvoke.FindContours(srcimage, Coutours, hierarchy, RetrType.List, ChainApproxMethod.LinkRuns, new Point(0, 0));
            //imageBox1.Image = b2;

            //List<Rectangle> rects = new List<Rectangle>();
            //开始遍历
            for (int i = 0; i < Coutours.Size; i++)
            {
                //得到这个连通区域的外接矩形
                var rect = CvInvoke.BoundingRectangle(Coutours[i]);
                //var Rect = CvInvoke.MinAreaRect(Coutours[i]);
                //var Area = CvInvoke.ContourArea(Coutours[i]);
                //如果高度不足,或者长宽比太小,认为是无效数据,否则把矩形画到原图上
                if ((rect.Height > 13 && rect.Width > 13) && (rect.Height < srcimage.Rows / 4 || rect.Width < srcimage.Cols / 4)
                    && rect.Height < srcimage.Rows * 3 / 5 && rect.Left > srcimage.Cols / 6 && rect.Right < srcimage.Cols * 5 / 6
                    && rect.Top > srcimage.Rows / 4 && rect.Bottom < srcimage.Rows * 3 / 4)
                {

                    //int a = srcimage.Bitmap.GetPixel(rect.X + rect.Width / 2, rect.Y + rect.Height / 2).B;
                    var Rect = CvInvoke.MinAreaRect(Coutours[i]);
                    var Area = CvInvoke.ContourArea(Coutours[i]);
                    listRects.Add(rect);
                    //if (Area / (Rect.Size.Height * Rect.Size.Width) < 0.8)
                    //    dictRects.Add(rect, "一类");
                    //else if (Rect.Size.Height / Rect.Size.Width < 1.0 / 3.0 || Rect.Size.Height / Rect.Size.Width > 3.0)
                    //    dictRects.Add(rect, "一类");
                    //else if (Area > 2000)
                    //    dictRects.Add(rect, "一类");
                    //else
                    //    dictRects.Add(rect, "二类");
                    //CvInvoke.DrawContours(b1, b3, i, color);
                }
            }

            //foreach (var rect in listRects)
            //{
            //    Mat roiMat = new Mat(FilterImage.Mat,rect.Key);
            //    this.dictCoutours.Add(roiMat, rect.Key);
            //}
        }

        /// <summary>
        /// 20180323 修改人 於景瞵 
        /// ACE图像增强算法
        /// </summary>
        /// <param name="src"></param>
        /// <param name="MaxCG"></param>
        /// <param name="C"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        Matrix<byte> ACE(Matrix<byte> src, double MaxCG = 2.0, int Amount = 140, int Radius = 40)
        {
            //图像高宽
            int rows = src.Width;
            int cols = src.Height;

            //背景归0化
            //Matrix<byte> ThreArray = new Matrix<byte>(new Size(rows, cols));
            //CvInvoke.Threshold(src, ThreArray, 60, 1, ThresholdType.Otsu);
            //src._Mul(ThreArray);

            //源图像double初始化
            Matrix<double> Src = src.Convert<double>() / 255.0;
            //全局和局部均值标准差矩阵初始化
            Matrix<double> meanLocal = new Matrix<double>(new Size(rows, cols)); //图像局部均值  
            Matrix<double> varLocal = new Matrix<double>(new Size(rows, cols));  //图像局部方差  
            Matrix<double> meanGlobal = new Matrix<double>(new Size(rows, cols));//全局均值
            Matrix<double> varGlobal = new Matrix<double>(new Size(rows, cols)); //全局标准差  

            //局部均值和高频成分计算
            CvInvoke.Blur(Src, meanLocal, new Size(Radius, Radius), new Point(-1, -1));
            Matrix<double> highFreq = Src - meanLocal;//高频成分 

            //局部标准差计算
            varLocal = highFreq.Clone();
            varLocal._Mul(highFreq);
            CvInvoke.Blur(varLocal, varLocal, new Size(Radius, Radius), new Point(-1, -1));
            CvInvoke.Sqrt(varLocal, varLocal);

            //CGArr初始化
            Matrix<double> cGArr = new Matrix<double>(new Size(rows, cols));

            //全局均值与标准差计算
            MCvScalar meanGloble = new MCvScalar();
            MCvScalar stdGloble = new MCvScalar();
            CvInvoke.MeanStdDev(Src, ref meanGloble, ref stdGloble);

            //求取CGArr
            double D = Amount * stdGloble.V0 / 100;                             //CGArr系数
            Matrix<double> temp = new Matrix<double>(new Size(rows, cols)) + 1;
            CvInvoke.Divide(D * temp, varLocal, cGArr);
            //cGArr = Amount * varLocal / stdGloble.V0;

            //封顶CGArr
            Matrix<byte> tempArr = cGArr.Convert<byte>();                       //cgArr转byte
            Matrix<byte> hFArr = tempArr.Clone();                               //封顶高频系数
            CvInvoke.Threshold(tempArr, hFArr, MaxCG, 1, ThresholdType.Binary);
            cGArr._Mul(1.0 - hFArr.Convert<double>());
            cGArr = (MaxCG * hFArr.Convert<double>()) + cGArr;
            cGArr._Mul(highFreq);

            //返回值Byte化
            Matrix<byte> dst1 = ((meanLocal + cGArr) * 255).Convert<byte>();     //变增益方法
            //Mat dst2 = (meanLocal + Amount * highFreq).Convert<byte>().Mat;//恒增益方法

            return dst1;
        }

        #region graythresh灰度阈值子函数
        private static double[] getHist(byte[] img1)
        {
            int gray = 0;
            //int Width = img.GetLength(1);
            //int Height = img.GetLength(0);
            int length = img1.Length;
            double[] Hist = new double[256];
            double[] p = new double[256];
            double dSumHist = 0.0;

            Parallel.For(0, length, i =>
            {

                gray = img1[i];
                Hist[gray] += 1.0;

            });

            //不统计0项
            //Hist[0] = 0;

            dSumHist = Hist.Sum();

            for (int i = 0; i < 256; i++)
            {
                p[i] = Hist[i] / dSumHist;

            }

            return p;
        }

        private static int iGetMaxidFromSigma_b_squared(double[] p)
        {
            int iMaxid = 0;
            int Length = p.GetLength(0);
            double[] dOmege = new double[Length];
            double[] dMu = new double[Length];
            double dMuMax = 0.0;
            double[] dSigma_b_squared = new double[Length];
            double dMaxSigma = 0.0;

            for (int i = 0; i < Length; i++)
            {
                if (i == 0)
                    dOmege[i] = p[i];
                else
                    dOmege[i] = dOmege[i - 1] + p[i];
            }//get Omege


            for (int i = 0; i < Length; i++)
            {
                if (i == 0)
                    dMu[i] = p[i];
                else
                    dMu[i] = dMu[i - 1] + p[i] * (i + 1);
            }//get Mu
            dMuMax = dMu[Length - 1];//get MuMax


            for (int i = 0; i < Length; i++)
            {
                dSigma_b_squared[i] = (dMuMax * dOmege[i] - dMu[i]) * (dMuMax * dOmege[i] - dMu[i]) / (dOmege[i] * (1 - dOmege[i]));
                if (dMaxSigma < dSigma_b_squared[i])
                {
                    dMaxSigma = dSigma_b_squared[i];
                    iMaxid = i;
                }

            }//get dSigma_b_squared

            return iMaxid;
        }


        private static double graythresh(byte[] Input1)
        {
            double Th = new double();
            //int Length = Input.GetLength(0);
            //int Width = Input.GetLength(1);

            double[] p = getHist(Input1);
            Th = iGetMaxidFromSigma_b_squared(p);


            return Th;
        }
        #endregion

        /// <summary>
        /// 字符串转16进制Byte字节
        /// </summary>
        /// <param name="hexString">输入字符串</param>
        /// <returns>转化的Byte字节</returns>
        private byte[] strToToHexByte(string hexString)
        {
            hexString = hexString.Replace("-", "");
            if ((hexString.Length % 2) != 0)
                hexString += "20";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

        public double[] GetTemparture()
        {
            double[] Temparture = new double[4];
            if (this.frameMsg.TempData == null)
                return Temparture;
            byte[] Wen = strToToHexByte(this.frameMsg.TempData);
            if ((Wen[0] & 0xf0) >> 4 == 15)
                Temparture[0] = -(~Wen[1] + 1 + 256.0 * ~Wen[0]) / 16;
            else
                Temparture[0] = (Wen[1] + 256.0 * Wen[0]) / 16;

            if ((Wen[2] & 0xf0) >> 4 == 15)
                Temparture[1] = -(~Wen[3] + 1 + 256.0 * ~Wen[2]) / 16;
            else
                Temparture[1] = (Wen[3] + 256.0 * Wen[2]) / 16;

            if ((Wen[4] & 0xf0) >> 4 == 15)
                Temparture[2] = -(~Wen[5] + 1 + 256.0 * ~Wen[4]) / 16;
            else
                Temparture[2] = (Wen[5] + 256.0 * Wen[4]) / 16;

            if ((Wen[6] & 0xf0) >> 4 == 15)
                Temparture[3] = -(~Wen[7] + 1 + 256.0 * ~Wen[6]) / 16;
            else
                Temparture[3] = (Wen[7] + 256.0 * Wen[6]) / 16;
            return Temparture;
        }
    }

    public class FrameMsg
    {
        //public string Head;
        public string HeadLength;
        public string TairLength;
        public string DataLength;
        public string ImageNum;
        public string ChannelNum;
        public string SampNum;
        public string EncodedData;
        public string TempData;
        public string DigSmall;
        public string DianjiState;
        public string VerDefe;
        public string HorDefe;
        public string Kuozhan;
        public string Tair;
        public bool Isodd;

        public void Init(string msg)
        {
            this.HeadLength = msg.Substring(0, 2 * 2);
            this.TairLength = msg.Substring(2 * 2, 2 * 2);
            this.DataLength = msg.Substring(4 * 2, 4 * 2);
            this.ImageNum = msg.Substring(8 * 2, 4 * 2);
            this.ChannelNum = msg.Substring(12 * 2, 2 * 2);
            this.SampNum = msg.Substring(14 * 2, 2 * 2);
            this.EncodedData = msg.Substring(16 * 2, 4 * 2);
            this.TempData = msg.Substring(20 * 2, 8 * 2);
            this.DigSmall = msg.Substring(28 * 2, 1 * 2);
            this.DianjiState = msg.Substring(29 * 2, 1 * 2);
            this.Kuozhan = msg.Substring(30 * 2, 6 * 2);

            this.Isodd = ((Convert.ToInt32(this.ImageNum, 16) & 0x01) == 1);
        }

        public void Init_v1(string msg)
        {
            this.HeadLength = msg.Substring(0, 2 * 2);
            this.TairLength = msg.Substring(2 * 2, 2 * 2);
            this.DataLength = msg.Substring(4 * 2, 4 * 2);
            this.ImageNum = msg.Substring(8 * 2, 4 * 2);
            this.ChannelNum = msg.Substring(12 * 2, 2 * 2);
            this.SampNum = msg.Substring(14 * 2, 2 * 2);
            //this.EncodedData = msg.Substring(16 * 2, 4 * 2);
            this.TempData = msg.Substring(16 * 2, 8 * 2);
            this.DigSmall = msg.Substring(24 * 2, 1 * 2);
            this.DianjiState = msg.Substring(25 * 2, 1 * 2);
            this.VerDefe = msg.Substring(26 * 2, 2 * 2);
            this.HorDefe = msg.Substring(28 * 2, 2 * 2);
            this.Kuozhan = msg.Substring(30 * 2, 6 * 2);

            this.Isodd = ((Convert.ToInt32(this.ImageNum, 16) & 0x01) == 1);
        }
    }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CSharp编程大全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档