// write minimal and maximal values of coordinates used for normalization and denormalization of data
        public static void writeMinMax <T, U>(char mode, CoordinatesContainer <T> minMax, CoordinatesContainer <U> faceModeMinMax = null)
        {
            bool          boolMode   = (mode == Constants.faceMode ? true : false);
            TextWriter    writer     = new StreamWriter(CaptureLabel.exportMinMaxDirectory, false, Encoding.UTF8);
            CsvSerializer serializer = new CsvSerializer(writer, System.Globalization.CultureInfo.CurrentCulture);
            CsvWriter     csv        = new CsvWriter(serializer);

            List <List <T> > minMaxT = new List <List <T> >(minMax.getCoordinates());

            minMaxT = Enumerable.Range(0, minMaxT[0].Count)
                      .Select(i => minMaxT.Select(lst => lst[i]).ToList()).ToList();

            csv.WriteField("");

            // check which mode is selected to construct appropriate header
            string[] rectNames = (boolMode) ? Constants.rectangleNameF : (mode == Constants.faceElementsMode ? Constants.rectangleNameE : Constants.rectangleNameG);

            // construct header
            foreach (string s in rectNames)
            {
                csv.WriteField(s);
                csv.WriteField("");
            }

            if (boolMode)
            {
                csv.WriteField("Face width:");
            }

            csv.NextRecord();
            csv.WriteField("");

            for (int i = 0; i < rectNames.Length; i++)
            {
                csv.WriteField("(x,");
                csv.WriteField("y)");
            }

            csv.NextRecord();
            csv.WriteField("Min:");

            // write minimal and maximal values to .csv file
            for (int i = 0; i < minMaxT.Count; i++)
            {
                for (int j = 0; j < minMaxT[i].Count; j++)
                {
                    csv.WriteField(minMaxT[i][j]);
                }

                if (mode == Constants.faceMode && faceModeMinMax != null)
                {
                    csv.WriteField(faceModeMinMax.getRow(0)[i]);
                }

                csv.NextRecord();
                csv.WriteField("Max:");
            }

            writer.Close();
        }
        // correct face rectangle coordinates because stored coordinates are coordinates
        // of top left corner of the rectangle and we need central point for neural network input
        public static void correctFaceCoordinates(CoordinatesContainer <int> realCoordinatesList, CoordinatesContainer <int> faceModeSize, List <double> imageResizeFactor, double scale, bool reverse = false)
        {
            int i = 0;

            // scale faceModeSize (face width) to get real coordinates of face right
            if (!reverse)
            {
                foreach (List <int> l in faceModeSize.getCoordinates())
                {
                    l[0] = (int)(Math.Round(l[0] / imageResizeFactor[i], MidpointRounding.AwayFromZero));
                    i++;
                }
            }

            i = 0;
            // correction factor for the first if face mode
            foreach (List <int> l in realCoordinatesList.getCoordinates())
            {
                int halfWidth = (reverse == false ? faceModeSize.getRow(i)[0] / 2 : -faceModeSize.getRow(i)[0] / 2);
                l[0] = l[0] + halfWidth;
                l[1] = l[1] + (int)(Math.Round(halfWidth * scale, MidpointRounding.AwayFromZero));
                i++;
            }

            i = 0;
            // scale faceModeSize (face width) to get relative coordinates (rectangleCoordinates) of face right
            if (reverse)
            {
                foreach (List <int> l in faceModeSize.getCoordinates())
                {
                    l[0] = (int)(Math.Round(l[0] * imageResizeFactor[i], MidpointRounding.AwayFromZero));
                    i++;
                }
            }
        }
        // exports values to normalized .csv file based on current work mode
        private void exportNormalized()
        {
            Tuple <List <List <double> >, List <List <int> > > normalized;
            Tuple <List <List <double> >, List <List <int> > > normalizedFS;
            CoordinatesContainer <double> normalizedCoordinates;
            CoordinatesContainer <double> normalizedFaceSize;
            CoordinatesContainer <int>    minMaxCoord;
            CoordinatesContainer <int>    minMaxFS;

            // save current image index values
            saveCoordinates();

            // export logic for face mode
            if (mode == Constants.faceMode)
            {
                // correct face coordinates
                Utilities.correctFaceCoordinates(realCoordinatesList, faceModeSize, imageResizeFactor, Constants.modeFRectScale);

                // normalize coordinates and face size values
                normalized   = Utilities.normalizeOutput <double, int>(realCoordinatesList);
                normalizedFS = Utilities.normalizeOutput <double, int>(faceModeSize);

                // asing values to appropriate value containers
                normalizedCoordinates = new CoordinatesContainer <double>(normalized.Item1);
                minMaxCoord           = new CoordinatesContainer <int>(normalized.Item2);
                normalizedFaceSize    = new CoordinatesContainer <double>(normalizedFS.Item1);
                minMaxFS = new CoordinatesContainer <int>(normalizedFS.Item2);


                // write normalized coordinates .csv file
                Utilities.writeToCSV(mode, normalizedCoordinates, imageNames, lookAngleContainer, normalizedFaceSize,
                                     isFacePresent, normalized: true);

                // create .csv file with minimal and maximal values needed for denormalization
                Utilities.writeMinMax(mode, minMaxCoord, minMaxFS);

                // correct face coordinates
                Utilities.correctFaceCoordinates(realCoordinatesList, faceModeSize, imageResizeFactor, Constants.modeFRectScale, true);
            }
            // export logic for face elements mode and eye countour mode
            else
            {
                // normalize coordinates and face size values
                normalized   = Utilities.normalizeOutput <double, int>(realCoordinatesList, faceModeSize, Constants.faceElementsMode);
                normalizedFS = Utilities.normalizeOutput <double, int>(faceModeSize);

                // asing values to appropriate value containers
                normalizedCoordinates = new CoordinatesContainer <double>(normalized.Item1);
                minMaxCoord           = new CoordinatesContainer <int>(normalized.Item2);
                normalizedFaceSize    = new CoordinatesContainer <double>(normalizedFS.Item1);
                minMaxFS = new CoordinatesContainer <int>(normalizedFS.Item2);

                // write normalized coordinates .csv file
                Utilities.writeToCSV(mode, normalizedCoordinates, imageNames, lookAngleContainer,
                                     faceModeSize, eyesNotVisibleContainer: eyesNotVisibleContainer, elementState: eyeClosed, normalized: true);
                // create .csv file with minimal and maximal values needed for denormalization
                Utilities.writeMinMax(mode, minMaxCoord, minMaxFS);
            }
        }
        // parsing face elements mode values from .csv file
        public static Tuple <List <int>, List <CoordinatesContainer <int> > > parseFaceElements(List <List <int> > lines)
        {
            List <int> item1 = new List <int>();
            List <CoordinatesContainer <int> > item2 = new List <CoordinatesContainer <int> >();
            CoordinatesContainer <int>         eyesNotVisibleContainer = new CoordinatesContainer <int>();
            CoordinatesContainer <int>         realCoordinates         = new CoordinatesContainer <int>();
            CoordinatesContainer <int>         lookAngleContainer      = new CoordinatesContainer <int>();
            CoordinatesContainer <int>         faceModeSize            = new CoordinatesContainer <int>();

            List <int> singleRow = new List <int>();

            // interate rough rows of values and parse them appropriately
            foreach (List <int> line in lines)
            {
                singleRow.Add(line[0]);
                singleRow.Add(line[1]);

                List <int> temp = new List <int>(singleRow);
                eyesNotVisibleContainer.addRow(temp);
                singleRow.Clear();

                for (int i = 2; i < 12; i++)
                {
                    singleRow.Add(line[i]);
                }

                temp = new List <int>(singleRow);
                realCoordinates.addRow(temp);
                singleRow.Clear();

                for (int i = 12; i < 16; i++)
                {
                    singleRow.Add(line[i]);
                }

                temp = new List <int>(singleRow);
                lookAngleContainer.addRow(temp);
                singleRow.Clear();

                singleRow.Add(line[16]);

                temp = new List <int>(singleRow);
                faceModeSize.addRow(temp);
                singleRow.Clear();
            }

            item2.Add(realCoordinates);
            item2.Add(lookAngleContainer);
            item2.Add(faceModeSize);
            item2.Add(eyesNotVisibleContainer);

            return(Tuple.Create(item1, item2));
        }
        // clean up function
        // called when importing or re-importing data and when New is selected from the File menu
        private void cleanUp()
        {
            imagePathTB.ReadOnly = false;
            csvPathTB.ReadOnly   = false;

            csvFileName = "newCsv.csv";

            imageLocation       = null;
            imageNames          = null;
            imageResizeFactor   = null;
            imagePadX           = null;
            imagePadY           = null;
            rectangles          = null;
            coordinatesList     = null;
            realCoordinatesList = null;

            faceModeSize            = null;
            lookAngleContainer      = null;
            eyesNotVisibleContainer = null;
            isFacePresent           = null;
            eyeClosed = null;

            currentImageIndex = 0;
            isLoaded          = false;
            someoneIsInFocus  = false;
            savedAs           = false;

            imageLocation       = new List <string>();
            imageNames          = new List <string>();
            imageResizeFactor   = new List <double>();
            imagePadX           = new List <double>();
            imagePadY           = new List <double>();
            coordinatesList     = new CoordinatesContainer <int>();
            realCoordinatesList = new CoordinatesContainer <int>();

            faceModeSize            = new CoordinatesContainer <int>();
            lookAngleContainer      = new CoordinatesContainer <int>();
            eyesNotVisibleContainer = new CoordinatesContainer <int>();
            isFacePresent           = new List <int>();
            eyeClosed = new List <int>();
        }
        // write relevant information to .csv file that is not normalized
        public static void writeToCSV <T, U, X>(char mode, CoordinatesContainer <T> realCoordinatesList, List <string> imageNames,
                                                CoordinatesContainer <U> lookAngleContainer, CoordinatesContainer <X> faceModeSize,
                                                List <int> elementState = null, CoordinatesContainer <U> eyesNotVisibleContainer = null, bool normalized = false)
        {
            // should be embedded in try-catch
            string        csvPath    = (normalized == true ? CaptureLabel.exportDirectory : CaptureLabel.saveDirectory);
            TextWriter    writer     = new StreamWriter(@csvPath, false, Encoding.UTF8);
            CsvSerializer serializer = new CsvSerializer(writer, System.Globalization.CultureInfo.CurrentCulture);
            CsvWriter     csv        = new CsvWriter(serializer);

            csv.WriteField("");

            string[] rectNames = ((mode == Constants.faceMode) ? Constants.rectangleNameF : (mode == Constants.faceElementsMode ? Constants.rectangleNameE : Constants.rectangleNameG));

            // construct header
            if (mode == Constants.faceMode)
            {
                csv.WriteField("noFace");
            }
            if (mode == Constants.faceElementsMode)
            {
                csv.WriteField("noLeftEye");
                csv.WriteField("noRightEye");
            }
            if (mode == Constants.eyeContourMode)
            {
                csv.WriteField("eyeClosed");
            }

            foreach (string s in rectNames)
            {
                csv.WriteField(s);
                csv.WriteField("");
            }

            foreach (string s in Constants.lookingAngleString)
            {
                csv.WriteField(s);
            }

            if (mode == Constants.eyeContourMode)
            {
                csv.WriteField("Eye width:");
            }
            else
            {
                csv.WriteField("Face width:");
            }

            csv.NextRecord();

            csv.WriteField("Picture:");
            csv.WriteField("");
            if (mode == Constants.faceElementsMode)
            {
                csv.WriteField("");
            }

            for (int i = 0; i < rectNames.Length; i++)
            {
                csv.WriteField("(x,");
                csv.WriteField("y)");
            }

            csv.NextRecord();

            // write rectangle coordinates to .csv file based on mode
            for (int i = 0; i < realCoordinatesList.getSize(); i++)
            {
                csv.WriteField(imageNames[i]);

                if (mode != Constants.faceElementsMode)
                {
                    csv.WriteField(elementState[i]);
                }
                if (mode == Constants.faceElementsMode)
                {
                    foreach (U value in eyesNotVisibleContainer.getRow(i))
                    {
                        csv.WriteField(value);
                    }
                }

                foreach (T value in realCoordinatesList.getRow(i))
                {
                    csv.WriteField(value);
                }

                foreach (U value in lookAngleContainer.getRow(i))
                {
                    csv.WriteField(value);
                }

                csv.WriteField(faceModeSize.getRow(i)[0]);


                csv.NextRecord();
            }

            writer.Close();
        }
        // normalize output values for face elements and eye countour mode
        public static Tuple <List <List <T> >, List <List <int> > > normalizeOutputFaceElements <T, U>(CoordinatesContainer <U> realCoordinatesList, CoordinatesContainer <int> faceModeSize)
        {
            List <List <U> >   coordinates  = new List <List <U> >(realCoordinatesList.getCoordinates());
            List <List <int> > minMaxValues = new List <List <int> >();
            List <List <T> >   result       = new List <List <T> >();

            // normalize elements
            int i = 0;

            foreach (List <U> l in coordinates)
            {
                int faceWidth = faceModeSize.getRow(i)[0];

                List <T> temp = new List <T>();

                // normalize output with formula:
                // Xnorm = (X - Xmin) / (Xmax - Xmin)
                for (int j = 0; j < l.Count; j += 2)
                {
                    double valX = (double)(Convert.ToDouble(l[j]) / faceWidth);
                    double valY = (double)(Convert.ToDouble(l[j + 1]) / (faceWidth * Constants.modeFRectScale));

                    // if value is not a number set it to zero
                    if (Double.IsNaN(valX) || Double.IsNaN(valY))
                    {
                        valX = 0;
                        valY = 0;
                    }
                    temp.Add((T)(object)valX);
                    temp.Add((T)(object)valY);
                }

                result.Add(temp);
                i++;
            }


            return(Tuple.Create(result, minMaxValues));
        }
        // normalize output values for face mode
        public static Tuple <List <List <T> >, List <List <int> > > normalizeOutputFaceMode <T, U>(CoordinatesContainer <U> realCoordinatesList)
        {
            List <List <U> >   coordinates  = new List <List <U> >(realCoordinatesList.getCoordinates());
            List <List <int> > minMaxValues = new List <List <int> >();
            List <List <T> >   result       = new List <List <T> >();

            // transpose elements
            coordinates = Enumerable.Range(0, coordinates[0].Count)
                          .Select(i => coordinates.Select(lst => lst[i]).ToList()).ToList();

            // normalize elements
            foreach (List <U> l in coordinates)
            {
                int min = Convert.ToInt32(l.Min());
                int max = Convert.ToInt32(l.Max());

                minMaxValues.Add(new List <int>()
                {
                    min, max
                });

                List <T> temp = new List <T>();

                // normalize output with formula:
                // Xnorm = (X - Xmin) / (Xmax - Xmin)
                for (int i = 0; i < l.Count; i++)
                {
                    double val = (double)(Convert.ToInt32(l[i]) - min) / (max - min);

                    // if value is not a number set it to zero
                    if (Double.IsNaN(val))
                    {
                        val = 0;
                    }

                    temp.Add((T)(object)val);
                }

                result.Add(temp);
            }

            // transpose elements
            result = Enumerable.Range(0, result[0].Count)
                     .Select(i => result.Select(lst => lst[i]).ToList()).ToList();


            return(Tuple.Create(result, minMaxValues));
        }
        // called as part of the private void exportNormalized() function
        // normalize output values to be saved to new .csv file
        public static Tuple <List <List <T> >, List <List <int> > > normalizeOutput <T, U>(CoordinatesContainer <U> realCoordinatesList, CoordinatesContainer <int> faceModeSize = null, char mode = 'f')
        {
            Tuple <List <List <T> >, List <List <int> > > normalized;

            if (mode == Constants.faceMode)
            {
                normalized = normalizeOutputFaceMode <T, U>(realCoordinatesList);
            }
            else
            {
                normalized = normalizeOutputFaceMode <T, U>(realCoordinatesList);
            }

            return(normalized);
        }
        // used for parsing face elements mode and eye contour mode .csv files
        public static Tuple <List <int>, List <CoordinatesContainer <int> > > parseTypeOneCSV(char mode, List <List <int> > lines)
        {
            List <int> item1 = new List <int>();
            List <CoordinatesContainer <int> > item2              = new List <CoordinatesContainer <int> >();
            CoordinatesContainer <int>         realCoordinates    = new CoordinatesContainer <int>();
            CoordinatesContainer <int>         lookAngleContainer = new CoordinatesContainer <int>();
            CoordinatesContainer <int>         faceModeSize       = new CoordinatesContainer <int>();

            List <int> singleRow = new List <int>();

            int iCoordLow  = 0;
            int iCoordHigh = 0;

            // sets starting reading positions base on the working mode
            if (mode == Constants.faceMode)
            {
                iCoordLow  = 7;
                iCoordHigh = 11;
            }
            else if (mode == Constants.eyeContourMode)
            {
                iCoordLow  = 11;
                iCoordHigh = 15;
            }

            // interate rough rows of values and parse them appropriately
            foreach (List <int> line in lines)
            {
                item1.Add(line[0]);

                for (int i = 1; i < iCoordLow; i++)
                {
                    singleRow.Add(line[i]);
                }

                List <int> temp = new List <int>(singleRow);
                realCoordinates.addRow(temp);
                singleRow.Clear();

                for (int i = iCoordLow; i < iCoordHigh; i++)
                {
                    singleRow.Add(line[i]);
                }

                temp = new List <int>(singleRow);
                lookAngleContainer.addRow(temp);
                singleRow.Clear();

                singleRow.Add(line[iCoordHigh]);

                temp = new List <int>(singleRow);
                faceModeSize.addRow(temp);
                singleRow.Clear();
            }

            item2.Add(realCoordinates);
            item2.Add(lookAngleContainer);
            item2.Add(faceModeSize);

            return(Tuple.Create(item1, item2));
        }
        // import button logic
        private void importButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            // release everything from memory before new import (or new import)
            cleanUp();

            // initialize selected mode
            initMode(mode);

            try
            {
                // get list of everything in folder passed to imageFolder
                imageLocation = new List <string>(Directory.GetFiles(imageFolder));
                csvFileName   = new DirectoryInfo(imageFolder).Name;

                var sortedFiles = Directory.GetFiles(@"C:\", "*").OrderByDescending(d => new FileInfo(d).CreationTime);

                // Parse list of image locations to contain only image locations
                imageLocation = Utilities.parseImagesToList(imageLocation);

                // import only if there are images found in folder
                if (imageLocation.Count > 0)
                {
                    // set imagePanel to first image
                    imagePanel.BackgroundImage = Image.FromFile(imageLocation[0]);
                    currentImageIndex          = 0;

                    // extract image names
                    foreach (string name in imageLocation)
                    {
                        imageNames.Add(Path.GetFileNameWithoutExtension(name));
                    }

                    // check for existing .csv file
                    if (!String.IsNullOrEmpty(csvPath) && csvPath.Contains(".csv"))
                    {
                        // parse .csv file based on mode selected
                        Tuple <List <int>, List <CoordinatesContainer <int> > > tempCSV = Utilities.parseCSV(csvPath, mode);

                        // set mode relevant fields
                        if (mode == Constants.faceMode)
                        {
                            isFacePresent = tempCSV.Item1;
                        }
                        if (mode == Constants.faceElementsMode)
                        {
                            eyesNotVisibleContainer = new CoordinatesContainer <int>(tempCSV.Item2[3]);
                        }
                        if (mode == Constants.eyeContourMode)
                        {
                            eyeClosed = tempCSV.Item1;
                        }

                        // set relevant fields to ones that are parsed from .csv file
                        realCoordinatesList = new CoordinatesContainer <int>(tempCSV.Item2[0]);
                        lookAngleContainer  = new CoordinatesContainer <int>(tempCSV.Item2[1]);
                        faceModeSize        = new CoordinatesContainer <int>(tempCSV.Item2[2]);

                        // calculate resize factor between original image and image on the imagePanel
                        for (int i = 0; i < imageNames.Count; i++)
                        {
                            imagePanel.BackgroundImage = Image.FromFile(imageLocation[i]);
                            calculateResizeFactor(i);
                            imagePanel.BackgroundImage.Dispose();
                        }

                        // correct face coordinates
                        if (mode == Constants.faceMode)
                        {
                            Utilities.correctFaceCoordinates(realCoordinatesList, faceModeSize, imageResizeFactor, Constants.modeFRectScale, true);
                        }

                        List <int> singleRow;
                        // set rectangle coordinates based on real one read from .csv file
                        for (int i = 0; i < realCoordinatesList.getSize(); i++)
                        {
                            singleRow = realCoordinatesList.getRow(i);
                            coordinatesList.addRow(new List <int>(calculateRectangleCoordinates(singleRow, i)));
                        }

                        // load currentImageIndex image from file and load associated coordinates
                        imagePanel.BackgroundImage = Image.FromFile(imageLocation[currentImageIndex]);
                        loadCoordinates(currentImageIndex);
                    }
                    imagePathTB.ReadOnly = true;
                    loaded = true;
                }
            }
            // catch if something went wrong in the section above
            catch (Exception msg)
            {
                imagePathTB.ReadOnly = false;
                MessageBox.Show(msg.Message, Constants.errorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            imagePanel.Refresh();

            Cursor.Current = Cursors.Default;
        }
Esempio n. 12
0
 // copy constructor
 public CoordinatesContainer(CoordinatesContainer <T> container)
 {
     rowCoordinates = new List <List <T> >(container.getCoordinates());
 }