// Path: src/main/java/com/tom_e_white/set_game/train/FindCardNumberFeatures.java
// public class FindCardNumberFeatures extends FeatureFinder {
// 
//   @Override
//   public int getLabelFromFilename(String filename) {
//     return Card.Number.parseFilename(new File(filename)).ordinal();
//   }
// 
//   @Override
//   public int getLabelFromDescription(String description) {
//     return Card.Number.parseDescription(description).ordinal();
//   }
// 
//   @Override
//   public double[] find(BufferedImage image, boolean debug) throws IOException {
//     // Based on code from http://boofcv.org/index.php?title=Example_Binary_Image
// 
//     ListDisplayPanel panel = debug ? new ListDisplayPanel() : null;
// 
//     List<Shape> shapes = ImageProcessingPipeline.fromBufferedImage(image, panel)
//             .gray()
//             .medianBlur(3) // this is fairly critical
//             .edges()
//             .dilate()
//             .contours()
//             .polygons(0.05, 0.05)
//             .getExternalShapes();
// 
//     int expectedWidth = 40 * 3; // 40mm
//     int expectedHeight = 20 * 3; // 20mm
//     int tolerancePct = 40;
//     List<Shape> filtered = GeometryUtils.filterByArea(shapes, expectedWidth, expectedHeight, tolerancePct);
//     List<Shape> nonOverlapping = GeometryUtils.filterNonOverlappingBoundingBoxes(filtered);
// 
//     if (debug) {
//       System.out.println(shapes);
//       System.out.println(filtered);
//       System.out.println(nonOverlapping);
//       ShowImages.showWindow(panel, "Binary Operations", true);
//     }
//     return new double[] { nonOverlapping.size() % 3 };  // just return as an int mod 3
//   }
// 
//   @Override
//   public String getFileSuffix() {
//     return "number.csv";
//   }
// 
//   @Override
//   public Classifier<double[]> getClassifier() throws IOException, ParseException {
//     return doubles -> ((int) doubles[0]) % 3; // just return as an int mod 3
//   }
// 
//   public static void main(String[] args) throws IOException {
//     BufferedImage image = UtilImageIO.loadImage(args[0]);
//     FindCardNumberFeatures featureFinder = new FindCardNumberFeatures();
//     double[] features = featureFinder.find(image, true);
//     System.out.println(featureFinder.getSummaryLine(args[0], features));
//   }
// 
// }


import com.tom_e_white.set_game.train.FindCardNumberFeatures;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import static com.tom_e_white.set_game.preprocess.TrainingDataV2.RAW_NEW_DIRECTORY;
import static com.tom_e_white.set_game.preprocess.TrainingDataV2.RAW_SORTED_DIRECTORY;
package com.tom_e_white.set_game.preprocess;




/**
 * Uses {@link FindCardNumberFeatures} to sort the raw training images by the number of shapes on each card (board).
 * Images are moved to <i>raw-sorted/&lt;num<gt;</i> directories, where they can be visually checked by a human.
 */
public class SortRawTrainingImagesV2 {
    public static void main(String[] args) throws IOException {
        RAW_SORTED_DIRECTORY.mkdirs();
// Path: src/main/java/com/tom_e_white/set_game/train/FindCardNumberFeatures.java
// public class FindCardNumberFeatures extends FeatureFinder {
// 
//   @Override
//   public int getLabelFromFilename(String filename) {
//     return Card.Number.parseFilename(new File(filename)).ordinal();
//   }
// 
//   @Override
//   public int getLabelFromDescription(String description) {
//     return Card.Number.parseDescription(description).ordinal();
//   }
// 
//   @Override
//   public double[] find(BufferedImage image, boolean debug) throws IOException {
//     // Based on code from http://boofcv.org/index.php?title=Example_Binary_Image
// 
//     ListDisplayPanel panel = debug ? new ListDisplayPanel() : null;
// 
//     List<Shape> shapes = ImageProcessingPipeline.fromBufferedImage(image, panel)
//             .gray()
//             .medianBlur(3) // this is fairly critical
//             .edges()
//             .dilate()
//             .contours()
//             .polygons(0.05, 0.05)
//             .getExternalShapes();
// 
//     int expectedWidth = 40 * 3; // 40mm
//     int expectedHeight = 20 * 3; // 20mm
//     int tolerancePct = 40;
//     List<Shape> filtered = GeometryUtils.filterByArea(shapes, expectedWidth, expectedHeight, tolerancePct);
//     List<Shape> nonOverlapping = GeometryUtils.filterNonOverlappingBoundingBoxes(filtered);
// 
//     if (debug) {
//       System.out.println(shapes);
//       System.out.println(filtered);
//       System.out.println(nonOverlapping);
//       ShowImages.showWindow(panel, "Binary Operations", true);
//     }
//     return new double[] { nonOverlapping.size() % 3 };  // just return as an int mod 3
//   }
// 
//   @Override
//   public String getFileSuffix() {
//     return "number.csv";
//   }
// 
//   @Override
//   public Classifier<double[]> getClassifier() throws IOException, ParseException {
//     return doubles -> ((int) doubles[0]) % 3; // just return as an int mod 3
//   }
// 
//   public static void main(String[] args) throws IOException {
//     BufferedImage image = UtilImageIO.loadImage(args[0]);
//     FindCardNumberFeatures featureFinder = new FindCardNumberFeatures();
//     double[] features = featureFinder.find(image, true);
//     System.out.println(featureFinder.getSummaryLine(args[0], features));
//   }
// 
// }


// Path: src/main/java/com/tom_e_white/set_game/preprocess/SortRawTrainingImagesV2.java
import com.tom_e_white.set_game.train.FindCardNumberFeatures;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import static com.tom_e_white.set_game.preprocess.TrainingDataV2.RAW_NEW_DIRECTORY;
import static com.tom_e_white.set_game.preprocess.TrainingDataV2.RAW_SORTED_DIRECTORY;

package com.tom_e_white.set_game.preprocess;




/**
 * Uses {@link FindCardNumberFeatures} to sort the raw training images by the number of shapes on each card (board).
 * Images are moved to <i>raw-sorted/&lt;num<gt;</i> directories, where they can be visually checked by a human.
 */
public class SortRawTrainingImagesV2 {
    public static void main(String[] args) throws IOException {
        RAW_SORTED_DIRECTORY.mkdirs();
        FindCardNumberFeatures cardFeatureCounter = new FindCardNumberFeatures();