// 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++; } } }
// 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(); }
// load coordinates of the current image index private bool loadCoordinates(int index) { // if there are no coordinates to load, return if (index >= realCoordinatesList.getSize()) { return(false); } // get corresponding coordinates and checkbox states List <int> singleRow = coordinatesList.getRow(index); List <int> faceSize = faceModeSize.getRow(index); lookAngle = new int[] { 0, 0, 0, 0 }; eyesNotVisible = new int[] { 0, 0 }; if (mode == Constants.faceMode) { noFaceCB.Checked = (isFacePresent[index] == 0 ? false : true); } if (mode == Constants.eyeContourMode) { eyeClosedCB.Checked = (eyeClosed[index] == 0 ? false : true); } // set rectangle positions and checkbox states based on retireved values if (singleRow != null) { rectangles.setAllRectCoordinates(singleRow); lookAngle = lookAngleContainer.getRow(index).ToArray(); if (mode == Constants.faceElementsMode) { eyesNotVisible = eyesNotVisibleContainer.getRow(index).ToArray(); setEyesCheckBoxes(new CheckBox[] { LEnotVCB, REnotVCB }); } if (mode == Constants.faceMode) { rectangles.setRectSize(0, new Size(faceSize[0], (int)(faceSize[0] * Constants.modeFRectScale))); } setCheckBoxes(new CheckBox[] { leftCB, rightCB, upCB, downCB }); return(true); } return(false); }
// 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)); }
// 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(); }
// save coordinates of the current image index private void saveCoordinates() { // save all rectangles coordinates List <int> coordinates = rectangles.getAllRectCoordinates(); double resizeFactor = 0; try { resizeFactor = imageResizeFactor[currentImageIndex]; } catch (ArgumentOutOfRangeException) { calculateResizeFactor(currentImageIndex); resizeFactor = imageResizeFactor[currentImageIndex]; } int faceWidth = (mode == Constants.faceMode) ? rectangles.getRectangles()[0].Width : imagePanel.BackgroundImage.Width; // calculate real coordinates if (coordinatesList.getRow(currentImageIndex) == null) { // add new properties associated with this image, some are based on current mode lookAngleContainer.addRow(lookAngle.ToList()); faceModeSize.addRow(new List <int> { faceWidth }); coordinatesList.addRow(coordinates); realCoordinatesList.addRow(calculateRealCoordinates(coordinates)); if (mode == Constants.faceMode) { isFacePresent.Add((noFaceCB.Checked ? 1 : 0)); } if (mode == Constants.faceElementsMode) { eyesNotVisibleContainer.addRow(eyesNotVisible.ToList()); } if (mode == Constants.eyeContourMode) { eyeClosed.Add((eyeClosedCB.Checked ? 1 : 0)); } } else { // replace new properties associated with this image, some are based on current mode lookAngleContainer.replaceRow(lookAngle.ToList(), currentImageIndex); coordinatesList.replaceRow(coordinates, currentImageIndex); realCoordinatesList.replaceRow(calculateRealCoordinates(coordinates), currentImageIndex); faceModeSize.replaceRow(new List <int> { faceWidth }, currentImageIndex); if (mode == Constants.faceMode) { isFacePresent[currentImageIndex] = (noFaceCB.Checked ? 1 : 0); } if (mode == Constants.faceElementsMode) { eyesNotVisibleContainer.replaceRow(eyesNotVisible.ToList(), currentImageIndex); } if (mode == Constants.eyeContourMode) { eyeClosed[currentImageIndex] = (eyeClosedCB.Checked ? 1 : 0); } } // set look angle and checkbox states lookAngle = new int[] { 0, 0, 0, 0 }; setCheckBoxes(new CheckBox[] { leftCB, rightCB, upCB, downCB }); if (mode == Constants.faceElementsMode) { eyesNotVisible = new int[] { 0, 0 }; setEyesCheckBoxes(new CheckBox[] { LEnotVCB, REnotVCB }); } if (mode == Constants.faceMode) { noFaceCB.Checked = false; } if (mode == Constants.eyeContourMode) { eyeClosedCB.Checked = false; } }
// 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; }