using System;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using System.IO.Ports;
using System.IO;
using System.Media;
using System.Drawing;
using System.Drawing.Imaging;
using System.Management;
using Lumenera.USB;
using OpenCvSharp;
using OpenCvSharp.ML;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
using System.Net.Sockets;  //System.Netの参照設定が必要です
using System.Diagnostics;
using System.Net;
using System.Threading;

namespace OperateCamera
{
    public partial class Form_TIASAutomaticShootingSystem : Form
    {
        // The port number for the remote device.
        private const int port = 2018;
        // ManualResetEvent instances signal completion.
        private static ManualResetEvent connectDone = new ManualResetEvent(false);
        private static ManualResetEvent sendDone = new ManualResetEvent(false);
        private static ManualResetEvent receiveDone = new ManualResetEvent(false);
        // The response from the remote device.
        private static String response = String.Empty;

        //Set user display window
        Form_Display Form_Display = new Form_Display();

        //Use the SuperpixelDLL
        [DllImport(@"SuperpixelDll.dll", EntryPoint = "superpixel", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        extern static IntPtr superpixel([MarshalAs(UnmanagedType.LPStr)]string name, string name2, string name3);

        //Set the path for playing audio files
        //SoundPlayer player1 = new SoundPlayer("chair_sit.wav");
        //SoundPlayer player2 = new SoundPlayer("chin_set.wav");
        //SoundPlayer player3 = new SoundPlayer("tongue_out.wav");
        //SoundPlayer player4 = new SoundPlayer("ShootingFailed.wav");
        //SoundPlayer player5 = new SoundPlayer("ShootingSuccess.wav");
        //SoundPlayer player6 = new SoundPlayer("result.wav");

        private FilterInfoCollection videoDevices;

        //Set the necessary parameters
        int sensor1;
        int sensor2;
        int timer1 = 0;
        int timer2 = 0;
        int timer3 = 0;
        int thresholdChair;
        int thresholdChin;
        int wait1 = 5;
        int wait2 = 5;
        public static int wait3 = 1;
        int start1 = 1;
        int start2 = 1;
        int check1;
        int check2;
        int check3 = 1;
        int sensor_count = 0;

        private float X;//The width of the current form
        private float Y;//The height of the current form

        IntPtr[] hcam;// Camera connection.
        int nbCamera = 0;
        int counter = 0;
        int[] imageSize;
        int syncHandle = 0;
        dll.LucamFrameFormat[] frame;
        dll.LucamSnapshot[] snap;
        dll.LucamConversion conversion;// Set the demosaic Method and color coreection matrix to use for the convertion to RGB.
        byte[][][] pdata;
        byte[][][] pBmp;
        Bitmap[][] bt;
        BitmapData btData;
        int nbLoop;

        //Set parameters of image
        OpenCvSharp.Rect[] tongues2;
        OpenCvSharp.Rect[] tongues3;
        Mat mat2;
        Mat mat3;
        Mat mat4;
        Mat mat5;
        Mat mat6;
        public static Bitmap bitmap;
        IntPtr sign;
        string signTostring;
        Mat foreground;
        string filepath;

        float[] a = new float [17];
        float[] b = new float [17];
        float[] c = new float [17];
        float d;
        float e;
        float f;
        int k;
        double m_R;
        double m_G;
        double m_B;
        float m_tongueL;
        float m_tonguea;
        float m_tongueb;
        float[] m_score = new float [5];
        int data_pointer = 0;
        float[] purple = new float[190 / 5];
        float[] darkred = new float[190 / 5];
        float[] crimson = new float[190 / 5];
        float[] pink = new float[190 / 5];
        float[] whitepink = new float[190 / 5];
        float[] inputData = new float[252];
        int rows = 84;
        int cols = 193;
        int startRow = 2;
        int startCol = 1;

        public static bool m_getColor = false;
        public static Mat m_CalibFrame; //キャリブレーション用画像
        Mat m_ConvertLab;
        Mat m_ConvertLabV;
        bool changedGain = false;
        Mat m_CalibFrameV; //キャリブレーション用画像
        bool m_xvCheck = true;
        public static OpenCvSharp.Point[] getRGBpoint = new OpenCvSharp.Point[24];//RGB取得用
        Mat[] roiBGR = new Mat[24];
        Mat[] roiBGRV = new Mat[24];
        double[] m_BforLabV = new double[24];
        double[] m_GforLabV = new double[24];
        double[] m_RforLabV = new double[24];
        double[] m_BforLab = new double[24];
        double[] m_GforLab = new double[24];
        double[] m_RforLab = new double[24];
        double[] m_B_calibration = new double[24];
        double[] m_G_calibration = new double[24];
        double[] m_R_calibration = new double[24];
        Mat translation;
        public static bool m_bCalib;
        public static OpenCvSharp.Point[] pt = new OpenCvSharp.Point[2];//キャリブレーション用のポイント入れ
        public static Mat m_PointedFrame; //ポイントされたMat
        public static int click = 0; //クリック回数
        double m_Gain_R;
        double m_Gain_G;
        double m_Gain_B;
        float Gainbule = 1;
        float Gaingrn1 = 1;
        float Gaingrn2 = 1;
        float Gainred = 1;

        //Serial communication
        public Form_TIASAutomaticShootingSystem()
        {
            InitializeComponent();
        }

        //Receive data from the microcontroller LOOP
        public void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                string data = serialPort1.ReadLine();//Read data line by line
                string[] strArrayData = new string[100];
                strArrayData = data.Split(' ');//Split the strings with spaces and store them in arrays respectively

                if(sensor_count > 2)
                {
                    //Change String Type into Int Type
                    int.TryParse(strArrayData[0], out sensor1);
                    int.TryParse(strArrayData[1], out sensor2);
                }

                //Output sensor value in textbox
                ReceiveDate_chair.Text = "";
                ReceiveDate_chair.AppendText(sensor1.ToString());

                ReceiveDate_chin.Text = "";
                ReceiveDate_chin.AppendText(sensor2.ToString());

                //Set three timer counters
                if (timer1 > 0) timer1--;
                if (timer2 > 0) timer2--;
                if (timer3 > 0) timer3--;

                //Set chair sensor trigger condition and trigger result
                if (sensor1 <= thresholdChair)
                {
                    while (timer1 == 0)
                    {
                        Form_Display.GuideBox.Text = "";
                        Form_Display.GuideBox.AppendText("Please Get To SIT");
                        this.GuideBox.Text = "";
                        this.GuideBox.AppendText("Please Get To SIT");
                        //player2.Stop();
                        //player3.Stop();
                        //player1.Play();

                        timer1 = 6;
                        timer2 = 0;
                        timer3 = 0;

                        StartClient("20");

                    }
                }

                //Set chin sensor trigger condition and trigger result
                if (sensor1 > thresholdChair && sensor2 < thresholdChin)
                {
                    while (timer2 == 0)
                    {
                        Form_Display.GuideBox.Text = "";
                        Form_Display.GuideBox.AppendText("Please Set Your CHIN");
                        this.GuideBox.Text = "";
                        this.GuideBox.AppendText("Please Set Your CHIN");
                        //player1.Stop();
                        //player3.Stop();
                        //player2.Play();

                        timer2 = 6;
                        timer1 = 0;
                        timer3 = 0;

                        StartClient("30");

                    }
                }

                //Set double trigger event
                if (sensor1 > thresholdChair && sensor2 > thresholdChin)
                {
                    while (timer3 == 0)
                    {
                        Form_Display.GuideBox.Text = "";
                        Form_Display.GuideBox.Text = "Please Stick Out Your Tongue Naturally";
                        this.GuideBox.Text = "";
                        this.GuideBox.Text = "Please Stick Out Your Tongue Naturally";
                        Form_Display.ShootingGuideBox.Text = "";
                        Form_Display.ShootingGuideBox.Text = "Make tip of your tongue near the green line!";
                        this.ShootingGuideBox.Text = "";
                        this.ShootingGuideBox.Text = "Make tip of your tongue near the green line!";
                        while (start2 == 1)
                        {
                            Camera_Connect();
                            start2 = 0;
                        }
                        //player1.Stop();
                        //player2.Stop();
                        //player3.Play();

                        timer3 = 5;
                        timer1 = 0;
                        timer2 = 0;

                        StartClient("40");

                    }
                }
                sensor_count++;
            }
        }

        //Load dialog box
        private void Form_TIASAutomaticShootingSystem_Load(object sender, EventArgs e)
        {
            pt[0].X = 0;
            pt[0].Y = 0;
            pt[1].X = 0;
            pt[1].Y = 0;

            Form_Display.Show();
            Form_Display.AxWindowsMediaPlayer.uiMode = "full";
            Form_Display.AxWindowsMediaPlayer.settings.setMode("loop", true);
            string[] serialPorts = GetDeviceNames();

            X = this.Width;//Get the width of the form
            Y = this.Height;//Get the height of the form
            setTag(this);//Invocation method

            foreach (string serialPort in serialPorts)
            {
                com_arduino.Items.Add(serialPort);
                if (com_arduino.Items.Count > 0)
                {
                    com_arduino.SelectedIndex = 0;
                }
            }

            try
            {
                //Show all the video input devices
                videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

                if (videoDevices.Count == 0)
                    throw new ApplicationException();

                foreach (FilterInfo device in videoDevices)
                {
                    com_cameras.Items.Add(device.Name);
                }
                com_cameras.SelectedIndex = 0;
            }
            catch (ApplicationException)
            {
                com_cameras.Items.Add("No local capture devices");
                videoDevices = null;
            }

            StartClient("Connected!");

        }

        //Closing dialog box
        private void Form_TIASAutomaticShootingSystem_FormClosing(object sender, FormClosingEventArgs e)
        {
            Invalidate();
        }

        private void Form_TIASAutomaticShootingSystem_Resize(object sender, EventArgs e)
        {
            float newx = (this.Width) / X; //Scale scaling of form
            float newy = (this.Height) / Y;//Height scaling of the form
            setControls(newx, newy, this);//Change the size of the control with the form
        }

        private void initB_Click()
        {
            nbLoop = 1;
            nbCamera = 1;

            if (nbCamera > 0)
            {
                hcam = new IntPtr[nbCamera];//Maybe 2 camera will be connected.
                frame = new dll.LucamFrameFormat[nbCamera];
                snap = new dll.LucamSnapshot[nbCamera];
                pdata = new byte[nbLoop][][];
                pBmp = new byte[nbLoop][][];
                bt = new Bitmap[nbLoop][];
                imageSize = new int[nbCamera];

                for (int i = 0; i < nbLoop; i++)
                {
                    pdata[i] = new byte[nbCamera][];
                    pBmp[i] = new byte[nbCamera][];
                    bt[i] = new Bitmap[nbCamera];
                }

                //Connection to camera;
                for (int i = 0; i < nbCamera; i++)
                {
                    hcam[i] = api.CameraOpen(i + 1);//Open camera to take frame from.

                    frame[i] = api.GetFormat(hcam[i]);//Read current frame format in the camera

                    //Prepare the snapshot.
                    snap[i].Exposure = Convert.ToSingle(20);
                    snap[i].ExposureDelay = 0;
                    snap[i].flReserved1 = 0;
                    snap[i].flReserved2 = 0;
                    snap[i].Format.BinningX = frame[i].BinningX;
                    snap[i].Format.BinningY = frame[i].BinningY;
                    snap[i].Format.FlagsX = frame[i].FlagsX;
                    snap[i].Format.FlagsY = frame[i].FlagsY;
                    snap[i].Format.Height = frame[i].Height;
                    snap[i].Format.PixelFormat = frame[i].PixelFormat;
                    snap[i].Format.Size = frame[i].Size;
                    snap[i].Format.SubSampleX = frame[i].SubSampleX;
                    snap[i].Format.SubSampleY = frame[i].SubSampleY;
                    snap[i].Format.Width = frame[i].Width;
                    snap[i].Format.X = frame[i].X;
                    snap[i].Format.Y = frame[i].Y;
                    snap[i].Gain = 1;
                    snap[i].GainBlue = Gainbule;
                    snap[i].GainGrn1 = Gaingrn1;
                    snap[i].GainGrn2 = Gaingrn2;
                    snap[i].GainRed = Gainred;
                    snap[i].ShutterType = dll.LucamShutterType.GlobalShutter;
                    snap[i].StrobeDelay = 0;
                    snap[i].StrobeFlags = 0;
                    snap[i].Timeout = 3000;
                    snap[i].UseHwTrigger = false;
                    imageSize[i] = (snap[i].Format.Width / snap[i].Format.SubSampleX) * (snap[i].Format.Height / snap[i].Format.SubSampleY);
                }

                for (int a = 0; a < nbLoop; a++)
                {
                    for (int i = 0; i < nbCamera; i++)
                    {
                        pdata[a][i] = new byte[imageSize[i]];
                        pBmp[a][i] = new byte[imageSize[i] * 3];
                    }
                }

                while(check3 == 1)
                {
                    check3 = 0;
                    syncHandle = api.EnableSynchronousSnapshots(nbCamera, hcam, snap);
                }
            }
        }

        private void takeFrame_Click()
        {
            //Take the frames 
            try
            {
                
                    api.TakeSynchronousSnapshots(syncHandle, pdata[0]);

                        conversion = new dll.LucamConversion(dll.LucamDemosaicMethod.FAST, dll.LucamCorrectionMatrix.IDENTITY);//Set the demosaic Method and color coreection matrix to use for the convertion to RGB.
                        dll.LucamConvertFrameToRgb24(hcam[counter], pBmp[0][counter], pdata[0][counter], frame[counter].Width / frame[counter].SubSampleX, frame[counter].Height / frame[counter].SubSampleY, frame[counter].PixelFormat, ref conversion);                       
                        bt[0][counter] = new Bitmap(frame[counter].Width, frame[counter].Height, PixelFormat.Format24bppRgb);//Create a new Windows bitmap.
                        btData = new BitmapData();
                        Rectangle lockdata = new Rectangle(0, 0, frame[counter].Width, frame[counter].Height);
                        btData = bt[0][counter].LockBits(lockdata, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb, btData);
                        System.Runtime.InteropServices.Marshal.Copy(pBmp[0][counter], 0, btData.Scan0, frame[counter].Height * frame[counter].Width * 3);
                        bt[0][counter].UnlockBits(btData);
                        bt[0][counter].RotateFlip(RotateFlipType.Rotate90FlipNone);

                        mat2 = new Mat(Form_Display.pictureBox1.Size.Height, Form_Display.pictureBox1.Size.Width, MatType.CV_8UC3, new Scalar(0, 0, 255));
                        mat3 = new Mat(Form_Display.pictureBox1.Size.Height, Form_Display.pictureBox1.Size.Width, MatType.CV_8UC3, 1);
                        mat4 = new Mat(Form_Display.pictureBox1.Size.Height, Form_Display.pictureBox1.Size.Width, MatType.CV_8UC3, 1);
                        mat5 = new Mat(Form_Display.pictureBox1.Size.Height, Form_Display.pictureBox1.Size.Width, MatType.CV_8UC3, 1);
                        mat6 = new Mat(Form_Display.pictureBox1.Size.Height, Form_Display.pictureBox1.Size.Width, MatType.CV_8UC3, 1);
                        mat2 = OpenCvSharp.Extensions.BitmapConverter.ToMat(bt[0][counter]);
                        Cv2.Resize(mat2, mat2, new OpenCvSharp.Size(512, 640), 0, 0, InterpolationFlags.Cubic);
                        mat5 = mat2.Clone();
                        mat6 = mat2.Clone();
                        Cv2.CvtColor(mat2, mat3, ColorConversionCodes.RGB2GRAY);
                        Cv2.EqualizeHist(mat3, mat4);
                        check1 = 0;
                        check2 = 0;
                        var objDetector = new CascadeClassifier("TongueDetector_v3.xml");
                        OpenCvSharp.Rect[] tongues = objDetector.DetectMultiScale(mat4, 1.1, 2, HaarDetectionType.ScaleImage, new OpenCvSharp.Size(50, 50));
                        foreach (OpenCvSharp.Rect tongue in tongues)
                        {
                            check1 = 1;

                            var center = new OpenCvSharp.Point
                            {
                                X = (int)(tongue.X + tongue.Width * 0.5),
                                Y = (int)(tongue.Y + tongue.Height * 0.5)
                            };
                            var axes = new OpenCvSharp.Size
                            {
                                Width = (int)(tongue.Width * 0.5),
                                Height = (int)(tongue.Height * 0.5)
                            };
                            var point1 = new OpenCvSharp.Point
                            {
                                X = (int)(tongue.X + tongue.Width * 0.3),
                                Y = (int)(tongue.Y + tongue.Height * 0.8)
                            };
                            var point2 = new OpenCvSharp.Point
                            {
                                X = (int)(tongue.X + tongue.Width * 0.7),
                                Y = (int)(tongue.Y + tongue.Height * 0.8)
                            };

                            Cv2.Rectangle(mat5, tongue, new Scalar(0, 0, 255), 3);
                            Cv2.Line(mat5, point1, point2, new Scalar(0, 255, 0), 5);
                            //Cv2.Ellipse(mat5, center, axes, 0, 0, 360, new Scalar(0, 0, 255), 5);

                            while (start1 == 1)
                            {
                                backgroundWorker3.RunWorkerAsync();
                                start1 = 0;
                            }
                        }

                        bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat5);
                        Form_Display.pictureBox1.Image = bitmap;
                        Form_Display.pictureBox1.Refresh();

                        if (wait1 == 0)
                        {
                            tongues2 = objDetector.DetectMultiScale(mat4, 1.1, 2, HaarDetectionType.ScaleImage, new OpenCvSharp.Size(50, 50));
                            foreach (OpenCvSharp.Rect tongue2 in tongues2)
                            {
                                check2 = 1;

                                bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat5);
                                this.pictureBox1.Image = bitmap;
                                Form_Display.pictureBox1.Image = bitmap;
                                this.pictureBox1.Refresh();
                                Form_Display.pictureBox1.Refresh();
                                //mat5.SaveImage("C:\\datasaved\\" + filepath + "example.jpg");
                            }
                            //break;
                        }
                        /*if (wait1 == 0)
                        {
                            break;
                        }
                    
                    if (wait1 == 0)
                    {
                        break;
                    }*/
                
            }
            catch
            {
                System.Windows.MessageBox.Show("Sorry cannot take Synchronous snapshot");
            }
        }

        public static string[] GetDeviceNames()
        {
            var deviceNameList = new System.Collections.ArrayList();
            var check = new System.Text.RegularExpressions.Regex("(COM[1-9][0-9]?[0-9]?)");

            ManagementClass mcPnPEntity = new ManagementClass("Win32_PnPEntity");
            ManagementObjectCollection manageObjCol = mcPnPEntity.GetInstances();

            //全てのPnPデバイスを探索しシリアル通信が行われるデバイスを随時追加する
            foreach (ManagementObject manageObj in manageObjCol)
            {
                //Nameプロパティを取得
                var namePropertyValue = manageObj.GetPropertyValue("Name");
                if (namePropertyValue == null)
                {
                    continue;
                }

                //Nameプロパティ文字列の一部が"(COM1)～(COM999)"と一致するときリストに追加"
                string name = namePropertyValue.ToString();
                if (check.IsMatch(name))
                {
                    deviceNameList.Add(name);
                }
            }

            //戻り値作成
            if (deviceNameList.Count > 0)
            {
                string[] deviceNames = new string[deviceNameList.Count];
                int index = 0;
                foreach (var name in deviceNameList)
                {
                    deviceNames[index++] = name.ToString();
                }
                return deviceNames;
            }
            else
            {
                return null;
            }
        }

        //Save the width, height, left distance, top margin, and font size of the control to the tag property
        //A control in a recursive control
        private void setTag(Control cons)
        {
            foreach (Control con in cons.Controls)
            {
                con.Tag = con.Width + ":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size;
                if (con.Controls.Count > 0)
                    setTag(con);
            }
        }

        //Adjust the size of the control according to the size of the form
        private void setControls(float newx, float newy, Control cons)
        {
            //Traversing the controls in the form, resetting the value of the control
            foreach (Control con in cons.Controls)
            {
                string[] mytag = con.Tag.ToString().Split(new char[] { ':' });//Get the Tag attribute value of the control and store the array of strings after splitting
                float a = System.Convert.ToSingle(mytag[0]) * newx;//Determine the value of the control according to the scale scale of the form, the width of the control
                con.Width = (int)a;//width
                a = System.Convert.ToSingle(mytag[1]) * newy;//height
                con.Height = (int)(a);
                a = System.Convert.ToSingle(mytag[2]) * newx;//Left distance
                con.Left = (int)(a);
                a = System.Convert.ToSingle(mytag[3]) * newy;//Upper edge distance
                con.Top = (int)(a);
                Single currentSize = System.Convert.ToSingle(mytag[4]) * newy;//font size
                con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
                if (con.Controls.Count > 0)
                {
                    setControls(newx, newy, con);
                }
            }
        }

        //Connect the specified camera button
        private void Camera_Connect()
        {
            Form_Display.label7.Visible = true;
            Form_Display.label10.Visible = true;

            Form_Display.pictureBox1.Visible = true;
            Form_Display.pictureBox2.Visible = true;

            Mat example = new Mat("example.jpg");
            bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(example);
            Form_Display.pictureBox2.Image = bitmap;
            Form_Display.pictureBox2.Refresh();

            backgroundWorker1.RunWorkerAsync();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            initB_Click();
            while (true)
            {
                takeFrame_Click();
                if (wait1 == 0)
                {
                    break;
                }
            }
            if(check2 == 1)
            {
                Form_Display.GuideBox.Text = "";
                Form_Display.GuideBox.Text = "SHOOTING SUCCESS!";
                Form_Display.ShootingGuideBox.Text = "";
                Form_Display.ShootingGuideBox.Text = "Loading...Please wait...";
                this.GuideBox.Text = "";
                this.GuideBox.Text = "SHOOTING SUCCESS!";
                this.ShootingGuideBox.Text = "";
                this.ShootingGuideBox.Text = "Loading...Please wait...";

                //player5.PlaySync();

                StartClient("50");

                //DateTime beforDT = System.DateTime.Now;

                Tosuperpixel();

                this.GuideBox.Text = "";
                this.GuideBox.Text = "Superpixel Success! Please wait...";

                grabcut();
                readfile_GainRGB();
                findROI();

                this.GuideBox.Text = "";
                this.GuideBox.Text = "Grabcut+FindROI Success! Please wait...";

                readfile();
                CalcLab();
                CalcSVM();
                Textshow();

                //DateTime afterDT = System.DateTime.Now;
                //TimeSpan ts = afterDT.Subtract(beforDT);
                //this.textBox1.Text = "";
                //this.textBox1.Text = ts.ToString();

                this.GuideBox.Text = "";
                this.GuideBox.Text = "SVM Data Contrast Success!";
                Form_Display.GuideBox.Text = "";
                Form_Display.GuideBox.Text = "ANALYZE SUCCESS!";
                Form_Display.ShootingGuideBox.Text = "";
                Form_Display.ShootingGuideBox.Text = "Complete!";
                this.ShootingGuideBox.Text = "";
                this.ShootingGuideBox.Text = "Complete!";

                //player6.Play();

                StartClient("60");

            }
            if (check2 == 0)
            {
                Form_Display.GuideBox.Text = "";
                Form_Display.GuideBox.Text = "SHOOTING FAILED!";
                this.GuideBox.Text = "";
                this.GuideBox.Text = "SHOOTING FAILED!";
                serialPort1.Close();
                timer1 = 0;
                timer2 = 0;
                timer3 = 0;
                //player4.Play();

                StartClient("51");

                while (wait2 > 0)
                {
                    Form_Display.ShootingGuideBox.Text = "";
                    Form_Display.ShootingGuideBox.Text = "Retry after" + wait2 + "seconds!";
                    this.ShootingGuideBox.Text = "";
                    this.ShootingGuideBox.Text = "Retry after" + wait2 + "seconds!";
                    System.Threading.Thread.Sleep(1000);
                    wait2--;
                }
                Restart();
            }
        }

        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            serialPort1.DataReceived += new
                SerialDataReceivedEventHandler(serialPort1_DataReceived);
        }

        private void backgroundWorker3_DoWork(object sender, DoWorkEventArgs e)
        {
            while(wait1 > 0)
            {
                if (check1 == 1)
                {
                    Form_Display.GuideBox.Text = "";
                    Form_Display.GuideBox.Text = "Please HOLD! The shooting will start in" + wait1 + "seconds!";
                    this.GuideBox.Text = "";
                    this.GuideBox.Text = "Please HOLD! The shooting will start in" + wait1 + "seconds!";
                    System.Threading.Thread.Sleep(1000);
                    wait1--;
                    if (check1 == 0)
                    {
                        Form_Display.GuideBox.Text = "Stick Out MORE!";
                        this.GuideBox.Text = "Stick Out MORE!";
                    }
                    if (wait1 == 0)
                    {
                        serialPort1.Close();
                        ReceiveDate_chair.Text = "";
                        ReceiveDate_chin.Text = "";
                        //player1.Stop();
                        //player2.Stop();
                        //player3.Stop();
                        Form_Display.GuideBox.Text = "";
                        Form_Display.GuideBox.Text = "Shooting..." ;
                        this.GuideBox.Text = "";
                        this.GuideBox.Text = "Shooting...";
                    }
                }
            }
        }

        private void Restart()
        {
            Form_Display.pictureBox1.Visible = false;
            Form_Display.pictureBox1.Image = null;
            Form_Display.pictureBox1.Refresh();
            this.pictureBox1.Image = null;
            this.pictureBox1.Refresh();
            Form_Display.pictureBox2.Visible = false;
            Form_Display.label7.Visible = false;
            Form_Display.label10.Visible = false;

            Form_Display.ShootingGuideBox.Text = "";
            this.ShootingGuideBox.Text = "";
            Form_Display.GuideBox.Text = "";
            this.GuideBox.Text = "";

            wait1 = 5;
            wait2 = 5;
            start1 = 1;
            start2 = 1;
            sensor_count = 0;
            serialPort1.Open();
        }

        private void grabcut()
        {
            const int GC_PR_FGD = 3;// 前景らしい領域を表す定数
            OpenCvSharp.Rect rectangle = tongues2[0];// 前景を含む領域
                                                     // 前景を抽出
            var result = new Mat(mat2.Size(), MatType.CV_8U);
            var bgdModel = new Mat();
            var fgdModel = new Mat();
            var source = new Mat(mat2.Size(), MatType.CV_8U, new Scalar(GC_PR_FGD));
            // GrabCutするイテレーションに???回を指定
            Cv2.GrabCut(mat6, result, rectangle, bgdModel, fgdModel, 5, GrabCutModes.InitWithRect);
            Cv2.Compare(result, source, result, CmpTypes.EQ);
            // 抽出した前景を貼り付ける画像、ソースと同サイズの真っ白な画像を指定
            foreground = new Mat(mat2.Size(), MatType.CV_8UC3, new Scalar(255, 255, 255));
            mat2.CopyTo(foreground, result);

            foreground.SaveImage("C:\\datasaved\\" + filepath + "grabcut.jpg");
        }

        private void Tosuperpixel()
        {
            filepath = DateTime.Now.ToString("yyyyMMddhhmmss");

            mat6.SaveImage("C:\\datasaved\\" + filepath + ".jpg");

            sign = superpixel("C:\\datasaved\\" + filepath + ".jpg", "C:\\datasaved\\" + filepath + "superpixel.jpg", "C:\\datasaved\\" + filepath + "super.jpg");
            signTostring = Marshal.PtrToStringAnsi(sign);

            Mat superpic = new Mat("C:\\datasaved\\" + filepath + "super.jpg");
            Mat superpixelpic = new Mat("C:\\datasaved\\" + filepath + "superpixel.jpg");

            bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(superpixelpic);
            this.pictureBox2.Image = bitmap;
            this.pictureBox2.Refresh();

            mat6 = superpic.Clone();
        }

        private void readfile_GainRGB()
        {
            System.Text.Encoding encoding = GetType("Gain.csv");
            System.IO.FileStream fs3 = new System.IO.FileStream("Gain.csv", System.IO.FileMode.Open, System.IO.FileAccess.Read);
            System.IO.StreamReader sr3 = new System.IO.StreamReader(fs3, encoding);

            //Record a row of records read each time
            string strLine = "";
            //Record the contents of each field in each row
            string[] aryLine = null;
            //Read the data in CSV by line by line
            while ((strLine = sr3.ReadLine()) != null)
            {
                aryLine = strLine.Split(',');
                d = Convert.ToSingle(aryLine[0]);
                e = Convert.ToSingle(aryLine[1]);
                f = Convert.ToSingle(aryLine[2]);
            }
            sr3.Close();
            fs3.Close();
        }

        private void findROI()
        {
            var objDetector = new CascadeClassifier("TongueDetector_v3.xml");
            tongues3 = objDetector.DetectMultiScale(mat4, 1.1, 2, HaarDetectionType.ScaleImage, new OpenCvSharp.Size(50, 50));
            foreach (OpenCvSharp.Rect tongue3 in tongues3)
            {
                var center = new OpenCvSharp.Point
                {
                    X = (int)(tongue3.X + tongue3.Width * 0.5),
                    Y = (int)(tongue3.Y + tongue3.Height * 0.68)
                };
                var axes = new OpenCvSharp.Size
                {
                    Width = (int)(20),
                    Height = (int)(20)
                };
                var point1 = new OpenCvSharp.Point
                {
                    X = (int)(tongue3.X + tongue3.Width * 0.3),
                    Y = (int)(tongue3.Y + tongue3.Height * 0.75)
                };
                var point2 = new OpenCvSharp.Point
                {
                    X = (int)(tongue3.X + tongue3.Width * 0.7),
                    Y = (int)(tongue3.Y + tongue3.Height * 0.75)
                };
                Cv2.Rectangle(foreground, tongue3, new Scalar(0, 0, 255), 3);
                Cv2.Ellipse(foreground, center, axes, 0, 0, 360, new Scalar(0, 0, 255), 3);
                //Cv2.Line(foreground, point1, point2, new Scalar(0, 255, 0), 5);

                bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(foreground);
                this.pictureBox3.Image = bitmap;
                this.pictureBox3.Refresh();

                foreground.SaveImage("C:\\datasaved\\" + filepath + "findROI.jpg");

                double[] meanBGR = new double[3];
                for (int i = 0; i < 2; i++)
                {
                    meanBGR[i] = 0;
                }

                // ROIを設定
                var temp = new Mat(mat2, new OpenCvSharp.Rect((int)(tongue3.X + tongue3.Width * 0.5 - 10), (int)(tongue3.Y + tongue3.Height * 0.68 - 10), 20, 20));
                // ROIを設定した領域を新しいMatとして切り出す
                var roiBGR = new Mat(20, 20, MatType.CV_8U);
                temp.CopyTo(roiBGR);

                bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(roiBGR);
                this.pictureBox4.Image = bitmap;
                this.pictureBox4.Refresh();

                roiBGR.SaveImage("C:\\datasaved\\" + filepath + "ROI.jpg");

                for (int i = 0; i < roiBGR.Height; i++)
                {
                    for (int j = 0; j < roiBGR.Width; j++)
                    {
                        meanBGR[0] = meanBGR[0] + roiBGR.At<Vec3b>(i, j).Item0; //B
                        meanBGR[1] = meanBGR[1] + roiBGR.At<Vec3b>(i, j).Item1; //G
                        meanBGR[2] = meanBGR[2] + roiBGR.At<Vec3b>(i, j).Item2; //R
                    }
                }
                m_B = meanBGR[0] / (roiBGR.Height * roiBGR.Width) * f;
                m_G = meanBGR[1] / (roiBGR.Height * roiBGR.Width) * e;
                m_R = meanBGR[2] / (roiBGR.Height * roiBGR.Width) * d;

                textBox9.Text = "";
                textBox9.Text = m_R.ToString("0.0");
                textBox10.Text = "";
                textBox10.Text = m_G.ToString("0.0");
                textBox11.Text = "";
                textBox11.Text = m_B.ToString("0.0");
            }
        }

        private void readfile()
        {
            System.Text.Encoding encoding = GetType("translateMatrixV.csv"); 
            System.IO.FileStream fs1 = new System.IO.FileStream("translateMatrixV.csv", System.IO.FileMode.Open, System.IO.FileAccess.Read);
            System.IO.StreamReader sr1 = new System.IO.StreamReader(fs1, encoding);

            for (int i = 0; i < 17; i++)
            {
                a[i] = 0;
                b[i] = 0;
                c[i] = 0;
            }

            k = 0;

            //Record a row of records read each time
            string strLine = "";
            //Record the contents of each field in each row
            string[] aryLine = null;
            //Read the data in CSV by line by line
            while ((strLine = sr1.ReadLine()) != null)
            {
                aryLine = strLine.Split(',');
                a[k] = Convert.ToSingle(aryLine[0]);
                b[k] = Convert.ToSingle(aryLine[1]);
                c[k] = Convert.ToSingle(aryLine[2]);
                k ++;
            }
            sr1.Close();
            fs1.Close();
        }

        private void CalcLab()
        {
            //XYZに変換
            double X, Y, Z;

            X = m_R * a[0] + m_G * a[1] + m_B * a[2]
                + a[3] * m_R * m_G + a[4] * m_R * m_B + a[5] * m_G * m_B
                + a[6] * m_R * m_R + a[7] * m_G * m_G + a[8] * m_B * m_B
                + a[9] * m_R * m_R * m_B + a[10] * m_R * m_R * m_G
                + a[11] * m_G * m_G * m_R + a[12] * m_G * m_G * m_B
                + a[13] * m_B * m_B * m_R + a[14] * m_B * m_B * m_G
                + a[15] * m_R * m_G * m_B
                + a[16];

            Y = m_R * b[0] + m_G * b[1] + m_B * b[2]
                + b[3] * m_R * m_G + b[4] * m_R * m_B + b[5] * m_G * m_B
                + b[6] * m_R * m_R + b[7] * m_G * m_G + b[8] * m_B * m_B
                + b[9] * m_R * m_R * m_B + b[10] * m_R * m_R * m_G
                + b[11] * m_G * m_G * m_R + b[12] * m_G * m_G * m_B
                + b[13] * m_B * m_B * m_R + b[14] * m_B * m_B * m_G
                + b[15] * m_R * m_G * m_B
                + b[16];

            Z = m_R * c[0] + m_G * c[1] + m_B * c[2]
                + c[3] * m_R * m_G + c[4] * m_R * m_B + c[5] * m_G * m_B
                + c[6] * m_R * m_R + c[7] * m_G * m_G + c[8] * m_B * m_B
                + c[9] * m_R * m_R * m_B + c[10] * m_R * m_R * m_G
                + c[11] * m_G * m_G * m_R + c[12] * m_G * m_G * m_B
                + c[13] * m_B * m_B * m_R + c[14] * m_B * m_B * m_G
                + c[15] * m_R * m_G * m_B
                + c[16];

            if (X < 0) X = 0;
            if (Y < 0) Y = 0;
            if (Z < 0) Z = 0;

            //Labに変換(固定の計算式)

            double Xn = 102.07;
            double Yn = 100.0;
            double Zn = 79.41;

            double cL = 116.0 * Math.Pow((Y / Yn), 1.0 / 3.0) - 16.0;
            double ca = 500.0 * (Math.Pow((X / Xn), 1.0 / 3.0) - Math.Pow((Y / Yn), 1.0 / 3.0));
            double cb = 200.0 * (Math.Pow((Y / Yn), 1.0 / 3.0) - Math.Pow((Z / Zn), 1.0 / 3.0));

            m_tongueL = float.Parse(cL.ToString());
            m_tonguea = float.Parse(ca.ToString());
            m_tongueb = float.Parse(cb.ToString());

            textBox6.Text = "";
            textBox6.Text = m_tongueL.ToString("0.0");
            textBox7.Text = "";
            textBox7.Text = m_tonguea.ToString("0.0");
            textBox8.Text = "";
            textBox8.Text = m_tongueb.ToString("0.0");
        }

        private void CalcSVM()
        {
            m_score[0] = 0;
            m_score[1] = 0;
            m_score[2] = 0;
            m_score[3] = 0;
            m_score[4] = 0;

            System.Text.Encoding encoding2 = GetType("data.csv");
            System.IO.FileStream fs2 = new System.IO.FileStream("data.csv", System.IO.FileMode.Open, System.IO.FileAccess.Read);
            System.IO.StreamReader sr2 = new System.IO.StreamReader(fs2, encoding2);

            string[] line_buffer = new string[1024];
            string line;
            Mat expData = new Mat(rows, cols, MatType.CV_32F);
            int readRow = 0, readCol = 0;

            for (int row = 0; ((line = sr2.ReadLine()) != null) && row < rows + startRow - 1; row++)
            {
                line_buffer = line.Split(',');

                if (row < startRow - 1) continue;

                data_pointer = 0;
                readCol = 0;

                for (int col = 0; col < cols + startCol - 1; col++)
                {
                    if (col >= startCol - 1)
                    {
                        float pix = Convert.ToSingle(line_buffer[data_pointer]);
                        expData.Set<float>(readRow, readCol, pix);
                        readCol++;
                    }
                    data_pointer++;
                }
                readRow++;
            }
            sr2.Close();
            fs2.Close();

            Mat testMat2 = new Mat(1, 3, MatType.CV_32FC1, new float[] { m_tongueL, m_tonguea, m_tongueb });

            //学習データ生成
            for (int r = 0; r < 84; r++)
            {
                for (int c2 = 0; c2 < 3; c2++)
                {
                    inputData[r * 3 + c2] = expData.At<float>(r, c2);
                }
            }

            Mat inputMat = new Mat(84, 3, MatType.CV_32FC1, inputData);

            //医師一人の場合
            float[] result = new float[190];
            for (int i = 0; i < 190; i++)
            {
                result[i] = 0.0f;
            }

            for (int id = 0; id < 190; id++)
            {
                int[] outputData = new int[84];
                for (int r = 0; r < 84; r++)
                {
                    outputData[r] = (int)expData.At<float>(r, 3 + id);
                }
                Mat outputMat = new Mat(84, 1, MatType.CV_32SC1, outputData);

                //学習可否判定（2クラスなければ学習不可）
                int nonZero = 0;
                for (int r = 0; r < 84; r++) if (outputData[r] > 0) nonZero++;

                if (nonZero < 2)
                {
                    result[id] = 0;
                    continue;
                }

                //SVM学習
                SVM svm = SVM.Create();
                svm.Gamma = 0.011;
                svm.C = 12.0;
                svm.Degree = 10.0;
                svm.Coef0 = 1.0;
                svm.Nu = 0.5;
                svm.P = 0.1;
                svm.Type = SVM.Types.CSvc;
                svm.KernelType = SVM.KernelTypes.Rbf;
                svm.TermCriteria = new TermCriteria(CriteriaType.Eps, 1000, 1.192092896e-07F);
                svm.Train(inputMat, SampleTypes.RowSample, outputMat);

                //SVM予測
                result[id] = svm.Predict(testMat2);
            }

            //信頼度算出
            float[] reliability = new float[190];
            for (int i = 0; i < 190; i++)
            {
                reliability[i] = 1.0f;
            }

            //それぞれ色の頭文字
            //信頼度は未使用
            int pu = 0;
            int d = 0;
            int c = 0;
            int pi = 0;
            int w = 0;

            for (int i = 0; i < 190 / 5; i++)
            {
                purple[i] = 0;
                darkred[i] = 0;
                crimson[i] = 0;
                pink[i] = 0;
                whitepink[i] = 0;
            }

            for (int i = 0; i < 190; i++)
            {
                if (i % 5 == 0)
                {
                    purple[pu] = result[i];
                    pu++;
                }
                if (i % 5 == 1)
                {
                    darkred[d] = result[i];
                    d++;
                }
                if (i % 5 == 2)
                {
                    crimson[c] = result[i];
                    c++;
                }
                if (i % 5 == 3)
                {
                    pink[pi] = result[i];
                    pi++;
                }
                if (i % 5 == 4)
                {
                    whitepink[w] = result[i];
                    w++;
                }
            }

            m_score[0] = 0;
            m_score[1] = 0;
            m_score[2] = 0;
            m_score[3] = 0;
            m_score[4] = 0;

            for (int j = 0; j < (190 / 5); j++)
            {
                m_score[0] = m_score[0] + purple[j];
                m_score[1] = m_score[1] + darkred[j];
                m_score[2] = m_score[2] + crimson[j];
                m_score[3] = m_score[3] + pink[j];
                m_score[4] = m_score[4] + whitepink[j];
            }
            m_score[0] = m_score[0] / (190 / 5);
            m_score[1] = m_score[1] / (190 / 5);
            m_score[2] = m_score[2] / (190 / 5);
            m_score[3] = m_score[3] / (190 / 5);
            m_score[4] = m_score[4] / (190 / 5);
        }

        private void Textshow()
        {
            string tempPu;
            string tempD;
            string tempC;
            string tempPi;
            string tempW;

            float ftempPu = 100 * m_score[0];
            float ftempD = 100 * m_score[1];
            float ftempC = 100 * m_score[2];
            float ftempPi = 100 * m_score[3];
            float ftempW = 100 * m_score[4];

            tempPu = ftempPu.ToString("0");
            tempD = ftempD.ToString("0");
            tempC = ftempC.ToString("0");
            tempPi = ftempPi.ToString("0");
            tempW = ftempW.ToString("0");

            Form_Display.textBox1.Text = "";
            Form_Display.textBox1.Text = tempPu + "%";
            Form_Display.textBox2.Text = "";
            Form_Display.textBox2.Text = tempD + "%";
            Form_Display.textBox3.Text = "";
            Form_Display.textBox3.Text = tempC + "%";
            Form_Display.textBox4.Text = "";
            Form_Display.textBox4.Text = tempPi + "%";
            Form_Display.textBox5.Text = "";
            Form_Display.textBox5.Text = tempW + "%";

            Form_Display.pictureBox1.Visible = false;

            Form_Display.label14.Visible = true;
            Form_Display.label16.Visible = true;
            Form_Display.label17.Visible = true;
            Form_Display.label18.Visible = true;
            Form_Display.label19.Visible = true;
            Form_Display.label20.Visible = true;
            Form_Display.label1.Visible = true;
            Form_Display.label2.Visible = true;
            Form_Display.label3.Visible = true;
            Form_Display.label4.Visible = true;
            Form_Display.label6.Visible = true;
            Form_Display.panel1.Visible = true;
            Form_Display.panel2.Visible = true;
            Form_Display.panel3.Visible = true;
            Form_Display.panel4.Visible = true;
            Form_Display.panel5.Visible = true;

            Form_Display.textBox1.Visible = true;
            Form_Display.textBox2.Visible = true;
            Form_Display.textBox3.Visible = true;
            Form_Display.textBox4.Visible = true;
            Form_Display.textBox5.Visible = true;

            bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat2);
            Form_Display.pictureBox2.Image = bitmap;
            Form_Display.pictureBox2.Refresh();

            Form_Display.label7.Visible = false;
            Form_Display.label10.Visible = false;
        }

        private void button_restart_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Application.Restart();
            Invalidate();
        }

        public static System.Text.Encoding GetType(string FILE_NAME)
        {
            System.IO.FileStream fs = new System.IO.FileStream(FILE_NAME, System.IO.FileMode.Open,
                System.IO.FileAccess.Read);
            System.Text.Encoding r = GetType(fs);
            fs.Close();
            return r;
        }

        public static System.Text.Encoding GetType(System.IO.FileStream fs)
        {
            byte[] Unicode = new byte[] { 0xFF, 0xFE, 0x41 };
            byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF, 0x00 };
            byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF };
            System.Text.Encoding reVal = System.Text.Encoding.Default;

            System.IO.BinaryReader r = new System.IO.BinaryReader(fs, System.Text.Encoding.Default);
            int i;
            int.TryParse(fs.Length.ToString(), out i);
            byte[] ss = r.ReadBytes(i);
            if (IsUTF8Bytes(ss) || (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF))
            {
                reVal = System.Text.Encoding.UTF8;
            }
            else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00)
            {
                reVal = System.Text.Encoding.BigEndianUnicode;
            }
            else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41)
            {
                reVal = System.Text.Encoding.Unicode;
            }
            r.Close();
            return reVal;
        }

        private static bool IsUTF8Bytes(byte[] data)
        {
            int charByteCounter = 1;
            byte curByte;
            for (int i = 0; i < data.Length; i++)
            {
                curByte = data[i];
                if (charByteCounter == 1)
                {
                    if (curByte >= 0x80)
                    {
                        while (((curByte <<= 1) & 0x80) != 0)
                        {
                            charByteCounter++;
                        }
                        if (charByteCounter == 1 || charByteCounter > 6)
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    if ((curByte & 0xC0) != 0x80)
                    {
                        return false;
                    }
                    charByteCounter--;
                }
            }
            if (charByteCounter > 1)
            {
                throw new Exception("Error");
            }
            return true;
        }

        private void button_ConnectTIAS_Click_1(object sender, EventArgs e)
        {
            int.TryParse(textBox_chair.Text, out thresholdChair);
            int.TryParse(textBox_chin.Text, out thresholdChin);
            string selscted = (string)com_arduino.SelectedItem;
            string strtempa = "(";
            string strtempb = ")";
            int IndexofA = selscted.IndexOf(strtempa);
            int IndexofB = selscted.IndexOf(strtempb);
            string num = selscted.Substring(IndexofA + 1, IndexofB - IndexofA - 1);
            serialPort1.PortName = num;
            serialPort1.Open();
            if (backgroundWorker2.IsBusy) 
            {
                backgroundWorker2.CancelAsync();
            }
            backgroundWorker2.RunWorkerAsync();
            wait3 = 0;
            Form_Display.AxWindowsMediaPlayer.Ctlcontrols.stop();
            button_ConnectTIAS.Enabled = false;
            Form_Display.AxWindowsMediaPlayer.Visible = false;
            Form_Display.GuideBox.Visible = true;
            Form_Display.ShootingGuideBox.Visible = true;
            Form_Display.label5.Visible = true;
            Form_Display.pictureBox1.Visible = false;
            Form_Display.pictureBox1.Image = null;
            Form_Display.pictureBox1.Refresh();
            Form_Display.ShootingGuideBox.Text = "";
        }

        private void takeFrame()
        {
            //Take the frames 
            try
            {
                    api.TakeSynchronousSnapshots(syncHandle, pdata[0]);

                        conversion = new dll.LucamConversion(dll.LucamDemosaicMethod.FAST, dll.LucamCorrectionMatrix.IDENTITY);//Set the demosaic Method and color coreection matrix to use for the convertion to RGB.
                        dll.LucamConvertFrameToRgb24(hcam[counter], pBmp[0][counter], pdata[0][counter], frame[counter].Width / frame[counter].SubSampleX, frame[counter].Height / frame[counter].SubSampleY, frame[counter].PixelFormat, ref conversion);
                        bt[0][counter] = new Bitmap(frame[counter].Width, frame[counter].Height, PixelFormat.Format24bppRgb);//Create a new Windows bitmap.
                        btData = new BitmapData();
                        Rectangle lockdata = new Rectangle(0, 0, frame[counter].Width, frame[counter].Height);
                        btData = bt[0][counter].LockBits(lockdata, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb, btData);
                        System.Runtime.InteropServices.Marshal.Copy(pBmp[0][counter], 0, btData.Scan0, frame[counter].Height * frame[counter].Width * 3);
                        bt[0][counter].UnlockBits(btData);
                        bt[0][counter].RotateFlip(RotateFlipType.Rotate90FlipNone);
                        m_CalibFrame = OpenCvSharp.Extensions.BitmapConverter.ToMat(bt[0][counter]);
                        m_CalibFrameV = OpenCvSharp.Extensions.BitmapConverter.ToMat(bt[0][counter]);

                        bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(m_CalibFrame);
                        Form_Display.pictureBox1.Image = bitmap;
                        Form_Display.pictureBox1.Refresh();

                        /*if (wait3 == 0)
                        {
                            break;
                        }
                    
                    if (wait3 == 0)
                    {
                        break;
                    }*/
                
            }
            catch
            {
                System.Windows.MessageBox.Show("Sorry cannot take Synchronous snapshot");
            }
        }

        private void button_correction_Click(object sender, EventArgs e)
        {
            Form_Display.AxWindowsMediaPlayer.Ctlcontrols.stop();
            Form_Display.AxWindowsMediaPlayer.Visible = false;
            Form_Display.GuideBox.Visible = true;
            Form_Display.ShootingGuideBox.Visible = true;
            Form_Display.label5.Visible = true;
            m_bCalib = true;
            //Mat tempFrame;
            if (!m_getColor)
            {
                wait3 = 1;
                Camera_Connect_correction();
                Form_Display.GuideBox.Text = "";
                Form_Display.GuideBox.Text = "Set ColorChecker, Click up-right corner color-box(White)";
                Form_Display.ShootingGuideBox.Text = "";
                Form_Display.ShootingGuideBox.Text = "DON'T enlarge the window!";
            }

            if (m_getColor)
            {
                GetRGBpoint();
                Calibration();
                ChangeGain();
                //変換行列計算を入れる
                CalcTransMat();
                wait3 = 0;
                Form_Display.pictureBox1.Visible = false;
                Form_Display.pictureBox1.Image = null;
                Form_Display.pictureBox1.Refresh();
                Form_Display.GuideBox.Text = "";
                Form_Display.GuideBox.Text = "Color calibration success！";
                Form_Display.ShootingGuideBox.Text = "";
                Form_Display.ShootingGuideBox.Text = "Just run this once a day!";
            }
        }

        private void GetRGBpoint()
        {
            m_ConvertLab = m_CalibFrame.Clone();
            m_ConvertLabV = m_CalibFrameV.Clone();

            Mat checkColor;
            Mat checkColorV;

            Scalar meanBGR;
            Scalar meanBGRV;
            Mat[] roiBGR = new Mat[24];
            Mat[] roiBGRV = new Mat[24];

            int[] x = new int[24];
            int[] y = new int[24];

            for (int i = 0; i < 24; i++)
            {
                x[i] = 0;
                y[i] = 0;
            }

            checkColor = m_ConvertLab.Clone();
            checkColorV = m_ConvertLabV.Clone();

            for (int j = 0; j < 24; j++)
            {
                x[j] = getRGBpoint[j].X - 7;
                y[j] = getRGBpoint[j].Y + 7;
                roiBGR[j] = new Mat(checkColor, new OpenCvSharp.Rect((int)(x[j]), (int)(y[j]), 15, 15));

                if (m_xvCheck && changedGain)
                {
                    roiBGRV[j] = new Mat(checkColorV, new OpenCvSharp.Rect((int)(x[j]), (int)(y[j]), 15, 15));
                    meanBGRV = Cv2.Mean(roiBGRV[j]);

                    m_BforLabV[j] = meanBGRV[0] * m_Gain_B;
                    m_GforLabV[j] = meanBGRV[1] * m_Gain_G;
                    m_RforLabV[j] = meanBGRV[2] * m_Gain_R;
                }

                meanBGR = Cv2.Mean(roiBGR[j]);

                m_BforLab[j] = meanBGR[0];
                m_GforLab[j] = meanBGR[1];
                m_RforLab[j] = meanBGR[2];
            }

            string RGBfilename = "RGBV.csv";
            FileStream RGB_file = File.Open(RGBfilename, FileMode.OpenOrCreate, FileAccess.Write);
            RGB_file.Seek(0, SeekOrigin.Begin);
            RGB_file.SetLength(0);
            RGB_file.Close();
            StreamWriter RGB_data = new StreamWriter(RGBfilename);
            string s2 = "";
            double s1;
            for (int i = 0; i <= 23; i++)
            {
                s1 = m_RforLabV[i];
                s2 += s1.ToString() + ",";
                s1 = m_GforLabV[i];
                s2 += s1.ToString() + ",";
                s1 = m_BforLabV[i];
                s2 += s1.ToString() + ",";
                RGB_data.WriteLine(s2);
                s2 = "";
            }
            RGB_data.Close();

            m_bCalib = false;
            m_getColor = false;
        }

        private void Calibration()
        {
            Mat checkColor;

            Scalar meanBGR;
            Mat[] roiBGR = new Mat[24];

            int[] x = new int[24];
            int[] y = new int[24];

            for (int i = 0; i < 24; i++)
            {
                x[i] = 0;
                y[i] = 0;
            }

            checkColor = m_CalibFrame.Clone();

            for (int j = 0; j < 24; j++)
            {
                x[j] = getRGBpoint[j].X - 2;
                y[j] = getRGBpoint[j].Y + 2;

                roiBGR[j] = new Mat(checkColor, new OpenCvSharp.Rect((int)(x[j]), (int)(y[j]), 5, 5));

                meanBGR = Cv2.Mean(roiBGR[j]);

                m_B_calibration[j] = meanBGR[0];
                m_G_calibration[j] = meanBGR[1];
                m_R_calibration[j] = meanBGR[2];
            }
        }

        private void ChangeGain()
        {
            double tempR;
            double tempG;
            double tempB;

            tempR = m_R_calibration[18];
            tempG = m_G_calibration[18];
            tempB = m_B_calibration[18];

            m_Gain_R = 150 / tempR;
            m_Gain_G = 150 / tempG;
            m_Gain_B = 150 / tempB;

            string Gainfilename = "Gain.csv";
            FileStream Gain_file = File.Open(Gainfilename, FileMode.OpenOrCreate, FileAccess.Write);
            Gain_file.Seek(0, SeekOrigin.Begin);
            Gain_file.SetLength(0);
            Gain_file.Close();
            StreamWriter Gain_data = new StreamWriter(Gainfilename);
            string s2 = "";
            double s1;
            s1 = m_Gain_R;
            s2 += s1.ToString() + ",";
            s1 = m_Gain_R;
            s2 += s1.ToString() + ",";
            s1 = m_Gain_B;
            s2 += s1.ToString() + ",";
            Gain_data.WriteLine(s2);
            s2 = "";
            Gain_data.Close();

            wait3 = 1;
            backgroundWorker4.RunWorkerAsync();
            changedGain = true;
            GetRGBpoint();
        }

        private void CalcTransMat()
        {
            Mat RGBmat = new Mat(24, 17, MatType.CV_64F, new Scalar(1.0f));
            Mat RGBVmat = new Mat(24, 17, MatType.CV_64F, new Scalar(1.0f));
            Mat XYZmat = new Mat(24, 4, MatType.CV_64F, new Scalar(1.0f));
            Mat transtemp = new Mat(4, 3, MatType.CV_64F, new Scalar(1.0f));
            Mat transtempV = new Mat(4, 3, MatType.CV_64F, new Scalar(1.0f));

            System.Text.Encoding encoding3 = GetType("xyz.txt");
            System.IO.FileStream fs3 = new System.IO.FileStream("xyz.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read);
            System.IO.StreamReader sr3 = new System.IO.StreamReader(fs3, encoding3);
            string line;
            string[] split = new string[3];
            double valueX = 0, valueY = 0, valueZ = 0;
            for (int i = 0; i < 24; i++)
            {
                line = sr3.ReadLine();
                split = line.Split(' ');
                valueX = Convert.ToDouble(split[0]);
                valueY = Convert.ToDouble(split[1]);
                valueZ = Convert.ToDouble(split[2]);
                XYZmat.Set<double>(i, 0, valueX);
                XYZmat.Set<double>(i, 1, valueY);
                XYZmat.Set<double>(i, 2, valueZ);
            }
            sr3.Close();
            fs3.Close();

            //ROIの設定，平均値の算出
            for (int j = 0; j < 24; j++)
            {
                //順番
                //R,G,B,RG,RB,GB,R^2,G^2,B^2
                //R^2B,R^2G,G^2,R,G^2B,B^2R,B^2G,RGB
                RGBmat.Set<double>(j, 2, m_BforLab[j]);
                RGBmat.Set<double>(j, 1, m_GforLab[j]);
                RGBmat.Set<double>(j, 0, m_RforLab[j]);
                //2次の項
                RGBmat.Set<double>(j, 3, m_RforLab[j] * m_GforLab[j]);
                RGBmat.Set<double>(j, 4, m_RforLab[j] * m_BforLab[j]);
                RGBmat.Set<double>(j, 5, m_GforLab[j] * m_BforLab[j]);
                RGBmat.Set<double>(j, 6, m_RforLab[j] * m_RforLab[j]);
                RGBmat.Set<double>(j, 7, m_GforLab[j] * m_GforLab[j]);
                RGBmat.Set<double>(j, 8, m_BforLab[j] * m_BforLab[j]);
                //3次の項
                RGBmat.Set<double>(j, 9, m_RforLab[j] * m_RforLab[j] * m_BforLab[j]);
                RGBmat.Set<double>(j, 10, m_RforLab[j] * m_RforLab[j] * m_GforLab[j]);
                RGBmat.Set<double>(j, 11, m_GforLab[j] * m_GforLab[j] * m_RforLab[j]);
                RGBmat.Set<double>(j, 12, m_GforLab[j] * m_GforLab[j] * m_BforLab[j]);
                RGBmat.Set<double>(j, 13, m_BforLab[j] * m_BforLab[j] * m_RforLab[j]);
                RGBmat.Set<double>(j, 14, m_BforLab[j] * m_BforLab[j] * m_GforLab[j]);
                RGBmat.Set<double>(j, 15, m_RforLab[j] * m_BforLab[j] * m_GforLab[j]);
            }

            //ROIの設定，平均値の算出
            for (int j = 0; j < 24; j++)
            {
                //順番
                //R,G,B,RG,RB,GB,R^2,G^2,B^2
                //R^2B,R^2G,G^2,R,G^2B,B^2R,B^2G,RGB
                RGBVmat.Set<double>(j, 2, m_BforLabV[j]);
                RGBVmat.Set<double>(j, 1, m_GforLabV[j]);
                RGBVmat.Set<double>(j, 0, m_RforLabV[j]);
                //2V次の項							  
                RGBVmat.Set<double>(j, 3, m_RforLabV[j] * m_GforLabV[j]);
                RGBVmat.Set<double>(j, 4, m_RforLabV[j] * m_BforLabV[j]);
                RGBVmat.Set<double>(j, 5, m_GforLabV[j] * m_BforLabV[j]);
                RGBVmat.Set<double>(j, 6, m_RforLabV[j] * m_RforLabV[j]);
                RGBVmat.Set<double>(j, 7, m_GforLabV[j] * m_GforLabV[j]);
                RGBVmat.Set<double>(j, 8, m_BforLabV[j] * m_BforLabV[j]);
                //3V次の項
                RGBVmat.Set<double>(j, 9, m_RforLabV[j] * m_RforLabV[j] * m_BforLabV[j]);
                RGBVmat.Set<double>(j, 10, m_RforLabV[j] * m_RforLabV[j] * m_GforLabV[j]);
                RGBVmat.Set<double>(j, 11, m_GforLabV[j] * m_GforLabV[j] * m_RforLabV[j]);
                RGBVmat.Set<double>(j, 12, m_GforLabV[j] * m_GforLabV[j] * m_BforLabV[j]);
                RGBVmat.Set<double>(j, 13, m_BforLabV[j] * m_BforLabV[j] * m_RforLabV[j]);
                RGBVmat.Set<double>(j, 14, m_BforLabV[j] * m_BforLabV[j] * m_GforLabV[j]);
                RGBVmat.Set<double>(j, 15, m_RforLabV[j] * m_BforLabV[j] * m_GforLabV[j]);
            }

            Cv2.Solve(RGBmat, XYZmat, transtemp, DecompTypes.SVD);
            Cv2.Solve(RGBVmat, XYZmat, transtempV, DecompTypes.SVD);

            translation = transtempV.Clone();//変換行列

            string CSVfilename = "translateMatrixV.csv";
            FileStream CSV_file = File.Open(CSVfilename, FileMode.OpenOrCreate, FileAccess.Write);
            CSV_file.Seek(0, SeekOrigin.Begin);
            CSV_file.SetLength(0);
            CSV_file.Close();
            StreamWriter CSV_data = new StreamWriter(CSVfilename);
            string s2 = "";
            for (int i = 0; i <= 16; i++)
            {
                for (int j = 0; j <= 2; j++)
                {
                    double s1 = translation.At<double>(i, j);
                    s2 += s1.ToString() + ",";
                }
                CSV_data.WriteLine(s2);
                s2 = "";
            }
            CSV_data.Close();
        }

        private void Camera_Connect_correction()
        {
            Form_Display.pictureBox1.Visible = true;
            backgroundWorker4.RunWorkerAsync();
        }

        private void backgroundWorker4_DoWork(object sender, DoWorkEventArgs e)
        {
            initB_Click();
            while (true)
            {
                takeFrame();
                if (wait3 == 0)
                {
                    break;
                }
            }
        }

        private static void StartClient(string command)
        {
            // Connect to a remote device.
            try
            {
                // Establish the remote endpoint for the socket.
                // The name of the remote device is "host.contoso.com".
                //IPHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
                //IPAddress ipAddress = ipHostInfo.AddressList[0];
                IPAddress ipAddress = IPAddress.Parse("192.168.23.153");
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
                // Create a TCP/IP socket.
                Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                // Connect to the remote endpoint.
                client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
                connectDone.WaitOne();
                // Send test data to the remote device.
                Send(client, command);
                sendDone.WaitOne();
                // Receive the response from the remote device.
                //Receive(client);
                //receiveDone.WaitOne();
                // Write the response to the console.
                //Console.WriteLine("Response received : {0}", response);
                // Release the socket.
                client.Shutdown(SocketShutdown.Both);
                client.Close();
            }
            catch (Exception e)
            {
                //System.Windows.MessageBox.Show(e.ToString());
                //Console.WriteLine(e.ToString());
            }

        }

        private static void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.
                Socket client = (Socket)ar.AsyncState;
                // Complete the connection.
                client.EndConnect(ar);
                //System.Windows.MessageBox.Show("Socket connected to {0}", client.RemoteEndPoint.ToString());
                //Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
                // Signal that the connection has been made.
                connectDone.Set();
            }
            catch (Exception e)
            {
                //System.Windows.MessageBox.Show(e.ToString());
                //Console.WriteLine(e.ToString());
            }
        }

        private static void Send(Socket client, String data)
        {
            // Convert the string data to byte data using ASCII encoding.
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            // Begin sending the data to the remote device.
            client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.
                Socket client = (Socket)ar.AsyncState;
                // Complete sending the data to the remote device.
                int bytesSent = client.EndSend(ar);
                //Console.WriteLine("Sent {0} bytes to server.", bytesSent);
                // Signal that all bytes have been sent.
                sendDone.Set();
            }
            catch (Exception e)
            {
                //System.Windows.MessageBox.Show(e.ToString());
                //Console.WriteLine(e.ToString());
            }
        }
    }

    internal class StateObject
    {
        // Client socket.
        public Socket workSocket = null;
        // Size of receive buffer.
        public const int BufferSize = 256;
        // Receive buffer.
        public byte[] buffer = new byte[BufferSize];
        // Received data string.
        public StringBuilder sb = new StringBuilder();
    }
}