Remove old comments, change javadoc to public

This commit is contained in:
Blizzard Finnegan 2023-03-10 09:59:30 -05:00
parent 2ff959d8b4
commit 429386c428
No known key found for this signature in database
GPG key ID: DE547EDF547DDA49
8 changed files with 68 additions and 289 deletions

36
pom.xml
View file

@ -47,7 +47,6 @@
<artifactId>javacv-platform</artifactId> <artifactId>javacv-platform</artifactId>
<version>${opencv.version}</version> <version>${opencv.version}</version>
</dependency> </dependency>
<!-- So... turns out, the showImage call requires JavaFX Swing, but doesn't actually *say* it requires that. -->
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId> <artifactId>javafx-swing</artifactId>
@ -91,13 +90,6 @@
<artifactId>pi4j-plugin-pigpio</artifactId> <artifactId>pi4j-plugin-pigpio</artifactId>
<version>${pi4j.version}</version> <version>${pi4j.version}</version>
</dependency> </dependency>
<!-- JavaFX Import -->
<!--<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>-->
</dependencies> </dependencies>
<build> <build>
@ -184,30 +176,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>org.baxter.disco.ocr.GuiStarter</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>-->
</plugins> </plugins>
</build> </build>
<reporting> <reporting>
@ -216,9 +184,9 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.4.1</version> <version>3.4.1</version>
<configuration> <!--<configuration>
<show>private</show> <show>private</show>
</configuration> </configuration> -->
</plugin> </plugin>
</plugins> </plugins>
</reporting> </reporting>

View file

@ -18,14 +18,14 @@ import java.util.concurrent.locks.ReentrantLock;
* classes). * classes).
* *
* @author Blizzard Finnegan * @author Blizzard Finnegan
* @version 1.7.0, 06 Mar. 2023 * @version 1.7.1, 10 Mar. 2023
*/ */
public class Cli public class Cli
{ {
/** /**
* Complete build version number * Complete build version number
*/ */
private static final String version = "4.3.5"; private static final String version = "4.3.6";
/** /**
* Currently saved iteration count. * Currently saved iteration count.
@ -65,12 +65,10 @@ public class Cli
*/ */
public static final Lock LOCK = new ReentrantLock(); public static final Lock LOCK = new ReentrantLock();
//private static Thread safeThread;
//Start of program message; always runs first
static static
{ {
ErrorLogging.logError("START OF PROGRAM"); ErrorLogging.logError("DEBUG: START OF PROGRAM");
} }
public static void main(String[] args) public static void main(String[] args)
@ -354,13 +352,10 @@ public class Cli
MovementFacade.iterationMovement(true); MovementFacade.iterationMovement(true);
double tesseractValue = 0.0; double tesseractValue = 0.0;
//Main camera config loop
do do
{ {
//Show the menu
printCameraMenu(cameraList); printCameraMenu(cameraList);
//Pick a camera to configure
int userInput; int userInput;
String cameraName = ""; String cameraName = "";
do do
@ -370,12 +365,10 @@ public class Cli
userInput--; userInput--;
} while (cameraList.size() < userInput && userInput < 0); } while (cameraList.size() < userInput && userInput < 0);
//Leave do-while loop if the user asks to
if(userInput == (cameraList.size())) break; if(userInput == (cameraList.size())) break;
else if(userInput < 0) continue; else if(userInput < 0) continue;
else cameraName = cameraList.get((userInput)); else cameraName = cameraList.get((userInput));
//Single camera config loop
do do
{ {
//Press button twice, to make sure the DUT is awake //Press button twice, to make sure the DUT is awake
@ -384,17 +377,12 @@ public class Cli
MovementFacade.pressButton(); MovementFacade.pressButton();
try{ Thread.sleep(2000); } catch(Exception e){ ErrorLogging.logError(e); } try{ Thread.sleep(2000); } catch(Exception e){ ErrorLogging.logError(e); }
//Show image
File image = OpenCVFacade.showImage(cameraName); File image = OpenCVFacade.showImage(cameraName);
//Parse the image with Tesseract, to show user what the excel output will be
tesseractValue = TesseractFacade.imageToDouble(image); tesseractValue = TesseractFacade.imageToDouble(image);
//User input parsing
ConfigProperties modifiedProperty = null; ConfigProperties modifiedProperty = null;
do do
{ {
//list configurable settings
printCameraConfigMenu(cameraName,tesseractValue); printCameraConfigMenu(cameraName,tesseractValue);
userInput = (int)inputFiltering(inputScanner.nextLine(),Menus.CAMERA); userInput = (int)inputFiltering(inputScanner.nextLine(),Menus.CAMERA);
@ -422,7 +410,6 @@ public class Cli
} }
} while(modifiedProperty == null); } while(modifiedProperty == null);
//Toggle threshold/crop
if(modifiedProperty == ConfigProperties.THRESHOLD || if(modifiedProperty == ConfigProperties.THRESHOLD ||
modifiedProperty == ConfigProperties.CROP) modifiedProperty == ConfigProperties.CROP)
{ {
@ -431,11 +418,9 @@ public class Cli
ConfigFacade.setValue(cameraName,modifiedProperty,newValue); ConfigFacade.setValue(cameraName,modifiedProperty,newValue);
} }
//Redefine crop points
else if(modifiedProperty == ConfigProperties.CROP_X) else if(modifiedProperty == ConfigProperties.CROP_X)
{ OpenCVFacade.setCrop(cameraName); } { OpenCVFacade.setCrop(cameraName); }
//Modify number of composite frames, or threshold value
else if(modifiedProperty == ConfigProperties.COMPOSITE_FRAMES || else if(modifiedProperty == ConfigProperties.COMPOSITE_FRAMES ||
modifiedProperty == ConfigProperties.THRESHOLD_VALUE) modifiedProperty == ConfigProperties.THRESHOLD_VALUE)
{ {
@ -447,7 +432,6 @@ public class Cli
ConfigFacade.setValue(cameraName,modifiedProperty,userInput); ConfigFacade.setValue(cameraName,modifiedProperty,userInput);
} }
//Exit loop
else else
{ {
ConfigFacade.saveCurrentConfig(); ConfigFacade.saveCurrentConfig();
@ -457,7 +441,6 @@ public class Cli
} while(true); } while(true);
//Save the current config to the config file
ConfigFacade.saveCurrentConfig(); ConfigFacade.saveCurrentConfig();
println("Configuration complete!"); println("Configuration complete!");
} }
@ -467,15 +450,11 @@ public class Cli
*/ */
private static void setDUTSerials() private static void setDUTSerials()
{ {
//Get a list of available cameras
List<String> cameraList = new ArrayList<>(OpenCVFacade.getCameraNames()); List<String> cameraList = new ArrayList<>(OpenCVFacade.getCameraNames());
//Main serial setting loop
do do
{ {
//Main menu
printSerialMenu(cameraList); printSerialMenu(cameraList);
//Pick a camera to configure
int userInput; int userInput;
String cameraName = ""; String cameraName = "";
do do
@ -486,12 +465,9 @@ public class Cli
userInput--; userInput--;
} while (cameraList.size() < userInput || userInput < 0); } while (cameraList.size() < userInput || userInput < 0);
//Leave do-while loop if the user asks to
if(userInput == (cameraList.size())) break; if(userInput == (cameraList.size())) break;
else cameraName = cameraList.get((userInput)); else cameraName = cameraList.get((userInput));
//Save the serial number.
//No parsing is ever done on this serial number.
prompt("Enter the serial number you wish to use for this camera: "); prompt("Enter the serial number you wish to use for this camera: ");
ConfigFacade.setSerial(cameraName,inputScanner.nextLine()); ConfigFacade.setSerial(cameraName,inputScanner.nextLine());
@ -518,16 +494,12 @@ public class Cli
*/ */
private static void setActiveCameras() private static void setActiveCameras()
{ {
//Get available cameras
List<String> cameraList = new ArrayList<>(OpenCVFacade.getCameraNames()); List<String> cameraList = new ArrayList<>(OpenCVFacade.getCameraNames());
//Main loop
do do
{ {
//Print menu
printActiveToggleMenu(cameraList); printActiveToggleMenu(cameraList);
//Pick a camera to configure
int userInput; int userInput;
String cameraName = ""; String cameraName = "";
do do
@ -537,11 +509,9 @@ public class Cli
userInput--; userInput--;
} while (cameraList.size() < userInput || userInput < 0); } while (cameraList.size() < userInput || userInput < 0);
//Leave do-while loop if the user asks to
if(userInput == (cameraList.size())) break; if(userInput == (cameraList.size())) break;
else cameraName = cameraList.get((userInput)); else cameraName = cameraList.get((userInput));
//Toggle whether the camera is active, at the config level
double newValue = ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE); double newValue = ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE);
newValue = Math.abs(newValue - 1); newValue = Math.abs(newValue - 1);
ConfigFacade.setValue(cameraName,ConfigProperties.ACTIVE,newValue); ConfigFacade.setValue(cameraName,ConfigProperties.ACTIVE,newValue);
@ -561,22 +531,18 @@ public class Cli
//useful for multithreading, which isn't necessary in CLI //useful for multithreading, which isn't necessary in CLI
final int localIterations = iterationCount; final int localIterations = iterationCount;
//Save whether to prime the devices; defaults to false //Hide legacy functionality
boolean prime = false; boolean prime = false;
//Create a List of *active* cameras.
List<String> cameraList = new ArrayList<>(); List<String> cameraList = new ArrayList<>();
for(String cameraName : OpenCVFacade.getCameraNames()) for(String cameraName : OpenCVFacade.getCameraNames())
{ {
prime = (ConfigFacade.getValue(cameraName,ConfigProperties.PRIME) != 0) || prime; prime = (ConfigFacade.getValue(cameraName,ConfigProperties.PRIME) != 0) || prime;
if(ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE) != 0) if(ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE) != 0)
{
cameraList.add(cameraName); cameraList.add(cameraName);
} }
}
//Initialise the workbook, with the number of cameras and the final output location
DataSaving.initWorkbook(ConfigFacade.getOutputSaveLocation(),cameraList.size()); DataSaving.initWorkbook(ConfigFacade.getOutputSaveLocation(),cameraList.size());
//Wake the device, then wait to ensure they're awake before continuing //Wake the device, then wait to ensure they're awake before continuing
@ -584,7 +550,6 @@ public class Cli
MovementFacade.pressButton(); MovementFacade.pressButton();
try{ Thread.sleep(2000); } catch(Exception e){ ErrorLogging.logError(e); } try{ Thread.sleep(2000); } catch(Exception e){ ErrorLogging.logError(e); }
//Create final maps for result images, result values, and camera names
Map<File,Double> resultMap = new HashMap<>(); Map<File,Double> resultMap = new HashMap<>();
Map<String,File> cameraToFile = new HashMap<>(); Map<String,File> cameraToFile = new HashMap<>();
@ -595,7 +560,7 @@ public class Cli
} }
ErrorLogging.logError("DEBUG: Starting tests..."); ErrorLogging.logError("DEBUG: Starting tests...");
//Start actually running tests
//All portions of the test check with the GPIO Run/Pause switch before //All portions of the test check with the GPIO Run/Pause switch before
//continuing, using the Lock object. //continuing, using the Lock object.
for(int i = 0; i < localIterations; i++) for(int i = 0; i < localIterations; i++)
@ -611,7 +576,6 @@ public class Cli
do do
{ {
fail = false; fail = false;
//Move the fixture for one iteration, with whether or not the DUTs need to be primed
while(!LOCK.tryLock()) {} while(!LOCK.tryLock()) {}
MovementFacade.iterationMovement(prime); MovementFacade.iterationMovement(prime);
LOCK.unlock(); LOCK.unlock();
@ -619,9 +583,6 @@ public class Cli
//Wait for the DUT to display an image //Wait for the DUT to display an image
try{ Thread.sleep(2000); } catch(Exception e){ ErrorLogging.logError(e); } try{ Thread.sleep(2000); } catch(Exception e){ ErrorLogging.logError(e); }
//For all available cameras:
// take an image, process it, and save it to a file
// put that file into the camera name file Map
for(String cameraName : cameraList) for(String cameraName : cameraList)
{ {
while(!LOCK.tryLock()) {} while(!LOCK.tryLock()) {}
@ -633,9 +594,6 @@ public class Cli
LOCK.unlock(); LOCK.unlock();
} }
//ONCE ALL IMAGES ARE CREATED
//Re-iterate over list of cameras, parse the images with Tesseract, then add
//the parsed value to the map
for(String cameraName : cameraList) for(String cameraName : cameraList)
{ {
while(!LOCK.tryLock()) {} while(!LOCK.tryLock()) {}
@ -666,16 +624,13 @@ public class Cli
} }
while(fail); while(fail);
//Write all given values to the Excel file
while(!LOCK.tryLock()) {} while(!LOCK.tryLock()) {}
DataSaving.writeValues(i,resultMap,cameraToFile); DataSaving.writeValues(i,resultMap,cameraToFile);
LOCK.unlock(); LOCK.unlock();
//Clear the result map
//DO NOT CLEAR camera to file Map. This will change the order of the objects within it //DO NOT CLEAR camera to file Map. This will change the order of the objects within it
resultMap.clear(); resultMap.clear();
} }
//Alert the user to testing being complete
println("======================================="); println("=======================================");
println("Testing complete!"); println("Testing complete!");
} }

View file

@ -24,7 +24,7 @@ import org.apache.commons.configuration2.builder.fluent.Parameters;
* Can write to file when requested, reads from file on initial start. * Can write to file when requested, reads from file on initial start.
* *
* @author Blizzard Finnegan * @author Blizzard Finnegan
* @version 1.3.1, 09 Feb. 2023 * @version 1.3.2, 10 Mar. 2023
*/ */
public class ConfigFacade public class ConfigFacade
{ {
@ -44,7 +44,7 @@ public class ConfigFacade
/** /**
* Location to save output XLSX file to. * Location to save output XLSX file to.
*/ */
public static String outputSaveLocation = "outputData/" + private static String outputSaveLocation = "outputData/" +
(LocalDateTime.now().format(ErrorLogging.fileDatetime)) + ".xlsx"; (LocalDateTime.now().format(ErrorLogging.fileDatetime)) + ".xlsx";
/** /**
@ -73,16 +73,14 @@ public class ConfigFacade
*/ */
private static INIConfiguration CONFIG_STORE; private static INIConfiguration CONFIG_STORE;
//This block will ALWAYS run first.
static static
{ {
//Get config values
ErrorLogging.logError("Starting configuration setup..."); ErrorLogging.logError("Starting configuration setup...");
//Give CONFIG_STORE an intentionally bad value
CONFIG_STORE = null; CONFIG_STORE = null;
//See if a config file already exists
File configFile = new File(configFileLocation); File configFile = new File(configFileLocation);
boolean newConfig = true; boolean newConfig = true;
try{ newConfig = configFile.createNewFile(); } try{ newConfig = configFile.createNewFile(); }
catch(Exception e){ ErrorLogging.logError(e); } catch(Exception e){ ErrorLogging.logError(e); }
@ -90,7 +88,6 @@ public class ConfigFacade
CONFIG_BUILDER = new FileBasedConfigurationBuilder<>(INIConfiguration.class) CONFIG_BUILDER = new FileBasedConfigurationBuilder<>(INIConfiguration.class)
.configure(new Parameters().fileBased().setFile(configFile)); .configure(new Parameters().fileBased().setFile(configFile));
//Try to import the config
ErrorLogging.logError("Attempting to import config..."); ErrorLogging.logError("Attempting to import config...");
if(!newConfig) if(!newConfig)
{ {
@ -111,8 +108,6 @@ public class ConfigFacade
} }
} }
//If there isn't a config file yet (or rather, if we just made a new one)
//save the default values to it
else else
{ {
ErrorLogging.logError("Unable to import config. Loading defaults..."); ErrorLogging.logError("Unable to import config. Loading defaults...");
@ -121,24 +116,19 @@ public class ConfigFacade
else ErrorLogging.logError("Configuration settings set up!"); else ErrorLogging.logError("Configuration settings set up!");
} }
//Make necessary directories, if not already available
ErrorLogging.logError("Creating image storage directories..."); ErrorLogging.logError("Creating image storage directories...");
File imageLocation = new File(imageSaveLocation); File imageLocation = new File(imageSaveLocation);
imageLocation.mkdir(); imageLocation.mkdir();
File debugImageLocation = new File(imageSaveLocation + "/debug"); File setupImageLocation = new File(imageSaveLocation + "/config");
debugImageLocation.mkdir(); setupImageLocation.mkdir();
File configImageLocation = new File(imageSaveLocation + "/config");
configImageLocation.mkdir();
File outputFileDirectory = new File("outputData"); File outputFileDirectory = new File("outputData");
outputFileDirectory.mkdir(); outputFileDirectory.mkdir();
//Create a new output file
ErrorLogging.logError("Creating output file...."); ErrorLogging.logError("Creating output file....");
File outputFile = new File(outputSaveLocation); File outputFile = new File(outputSaveLocation);
try{ outputFile.createNewFile(); } try{ outputFile.createNewFile(); }
catch(Exception e){ ErrorLogging.logError(e); } catch(Exception e){ ErrorLogging.logError(e); }
//Autosave the config
CONFIG_BUILDER.setAutoSave(true); CONFIG_BUILDER.setAutoSave(true);
} }
@ -161,7 +151,6 @@ public class ConfigFacade
double output = 0.0; double output = 0.0;
if(!configMap.keySet().contains(cameraName)) if(!configMap.keySet().contains(cameraName))
{ {
//Log failure information
ErrorLogging.logError("CONFIG ERROR!!! - Invalid camera name: " + cameraName); ErrorLogging.logError("CONFIG ERROR!!! - Invalid camera name: " + cameraName);
ErrorLogging.logError("\tKey set: " + configMap.keySet().toString()); ErrorLogging.logError("\tKey set: " + configMap.keySet().toString());
ErrorLogging.logError("\tProperty: " + property.getConfig()); ErrorLogging.logError("\tProperty: " + property.getConfig());
@ -170,9 +159,6 @@ public class ConfigFacade
} }
Map<ConfigProperties,Double> cameraConfig = configMap.get(cameraName); Map<ConfigProperties,Double> cameraConfig = configMap.get(cameraName);
output = cameraConfig.get(property); output = cameraConfig.get(property);
//Debug logger.
//ErrorLogging.logError("DEBUG: getValue - return value: " + cameraName
// + "/" + property.getConfig() + " = " + output);
return output; return output;
} }
@ -240,12 +226,16 @@ public class ConfigFacade
public static boolean setValue(String cameraName, ConfigProperties property, double propertyValue) public static boolean setValue(String cameraName, ConfigProperties property, double propertyValue)
{ {
boolean output = false; boolean output = false;
List<String> activeCameras = new ArrayList<>(OpenCVFacade.getCameraNames()); List<String> activeCameras = new ArrayList<>(OpenCVFacade.getCameraNames());
if(!activeCameras.contains(cameraName)) return output; if(!activeCameras.contains(cameraName)) return output;
Map<ConfigProperties,Double> cameraConfig = configMap.get(cameraName); Map<ConfigProperties,Double> cameraConfig = configMap.get(cameraName);
if(cameraConfig == null) return output; if(cameraConfig == null) return output;
Double oldValue = cameraConfig.get(property); Double oldValue = cameraConfig.get(property);
output = cameraConfig.replace(property,oldValue,propertyValue); output = cameraConfig.replace(property,oldValue,propertyValue);
saveCurrentConfig(); saveCurrentConfig();
return output; return output;
} }
@ -288,21 +278,15 @@ public class ConfigFacade
*/ */
public static boolean saveDefaultConfig(String filename) public static boolean saveDefaultConfig(String filename)
{ {
//Get set of camera names
boolean output = false; boolean output = false;
Set<String> cameraNames = OpenCVFacade.getCameraNames(); Set<String> cameraNames = OpenCVFacade.getCameraNames();
//Set the config builder to a file-based, INI configuration,
//with the given filename
CONFIG_BUILDER = new FileBasedConfigurationBuilder<>(INIConfiguration.class) CONFIG_BUILDER = new FileBasedConfigurationBuilder<>(INIConfiguration.class)
.configure(new Parameters().fileBased() .configure(new Parameters().fileBased()
.setFile(new File(filename))); .setFile(new File(filename)));
//Set CONFIG_STORE to the Configuration created by the Builder
try { CONFIG_STORE = CONFIG_BUILDER.getConfiguration(); } try { CONFIG_STORE = CONFIG_BUILDER.getConfiguration(); }
catch(Exception e) { ErrorLogging.logError(e); } catch(Exception e) { ErrorLogging.logError(e); }
//If the save default fails, warn the user that something is wrong
finally finally
{ {
if(CONFIG_STORE == null) if(CONFIG_STORE == null)
@ -312,10 +296,6 @@ public class ConfigFacade
} }
} }
//Iterate over every camera
// Create a map of the default values
// Save the default values to the CONFIG_STORE
// save the map to the main config map
for(String camera : cameraNames) for(String camera : cameraNames)
{ {
Map<ConfigProperties,Double> cameraConfig = new HashMap<>(); Map<ConfigProperties,Double> cameraConfig = new HashMap<>();
@ -324,14 +304,11 @@ public class ConfigFacade
String propertyName = camera + "." + property.getConfig(); String propertyName = camera + "." + property.getConfig();
double propertyValue = property.getDefaultValue(); double propertyValue = property.getDefaultValue();
cameraConfig.put(property,propertyValue); cameraConfig.put(property,propertyValue);
//ErrorLogging.logError("DEBUG: Attempting to save to config: ");
//ErrorLogging.logError("DEBUG: " + propertyName + ", " + propertyValue);
CONFIG_STORE.setProperty(propertyName,propertyValue); CONFIG_STORE.setProperty(propertyName,propertyValue);
} }
configMap.put(camera,cameraConfig); configMap.put(camera,cameraConfig);
} }
//Save out to the file
try try
{ {
CONFIG_BUILDER.save(); CONFIG_BUILDER.save();
@ -442,7 +419,6 @@ public class ConfigFacade
for(ConfigProperties configState : ConfigProperties.values()) for(ConfigProperties configState : ConfigProperties.values())
{ {
Double configValue = CONFIG_STORE.getDouble(sectionName + "." + configState.getConfig()); Double configValue = CONFIG_STORE.getDouble(sectionName + "." + configState.getConfig());
//ErrorLogging.logError("DEBUG: Imported config value: " + Double.toString(configValue));
savedSection.put(configState,configValue); savedSection.put(configState,configValue);
} }
} }
@ -456,7 +432,6 @@ public class ConfigFacade
{ {
for(String key : configMap.keySet()) for(String key : configMap.keySet())
{ {
//ErrorLogging.logError("DEBUG: configMap Key: " + key + " ?= " + sectionName);
if( key.equals(sectionName)) if( key.equals(sectionName))
{ configMap.put(key,savedSection); } { configMap.put(key,savedSection); }
} }
@ -493,8 +468,6 @@ public class ConfigFacade
String propertyName = sectionName + "." + property.getConfig(); String propertyName = sectionName + "." + property.getConfig();
double propertyValue = property.getDefaultValue(); double propertyValue = property.getDefaultValue();
cameraConfig.put(property,propertyValue); cameraConfig.put(property,propertyValue);
//ErrorLogging.logError("DEBUG: Attempting to save to config: ");
//ErrorLogging.logError("DEBUG: " + propertyName + ", " + propertyValue);
CONFIG_STORE.setProperty(propertyName,propertyValue); CONFIG_STORE.setProperty(propertyName,propertyValue);
} }
configMap.put(sectionName,cameraConfig); configMap.put(sectionName,cameraConfig);

View file

@ -1,10 +1,10 @@
package org.baxter.disco.ocr; package org.baxter.disco.ocr;
import java.io.DataInputStream;
//Standard imports //Standard imports
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.DataInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -32,7 +32,7 @@ import static org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
* Facade for saving data out to a file. * Facade for saving data out to a file.
* *
* @author Blizzard Finnegan * @author Blizzard Finnegan
* @version 5.0.0, 07 Mar. 2023 * @version 5.0.1, 10 Mar. 2023
*/ */
public class DataSaving public class DataSaving
{ {
@ -99,16 +99,13 @@ public class DataSaving
//Create workbook, Sheet, and DataFormat object //Create workbook, Sheet, and DataFormat object
//HSSF objects are used, as these are compatible with Microsoft Excel //HSSF objects are used, as these are compatible with Microsoft Excel
//XSSF objects were initially used, but caused issues.
outputWorkbook = new HSSFWorkbook(); outputWorkbook = new HSSFWorkbook();
outputSheet = outputWorkbook.createSheet(); outputSheet = outputWorkbook.createSheet();
format = outputWorkbook.createDataFormat(); format = outputWorkbook.createDataFormat();
//Create a default style for values.
defaultStyle = outputWorkbook.createCellStyle(); defaultStyle = outputWorkbook.createCellStyle();
defaultStyle.setDataFormat(format.getFormat("0.0")); defaultStyle.setDataFormat(format.getFormat("0.0"));
//Create a style for the final percentage values
finalValuesStyle = outputWorkbook.createCellStyle(); finalValuesStyle = outputWorkbook.createCellStyle();
finalValuesStyle.setDataFormat(format.getFormat("0.000%")); finalValuesStyle.setDataFormat(format.getFormat("0.000%"));
@ -124,19 +121,16 @@ public class DataSaving
failStyle.setDataFormat(format.getFormat("0.0")); failStyle.setDataFormat(format.getFormat("0.0"));
failStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); failStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//Create a style for error-ed, but not out-of-range, values
errorStyle = outputWorkbook.createCellStyle(); errorStyle = outputWorkbook.createCellStyle();
errorStyle.setFillForegroundColor(HSSFColorPredefined.YELLOW.getIndex()); errorStyle.setFillForegroundColor(HSSFColorPredefined.YELLOW.getIndex());
errorStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); errorStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//Create the header
int startingRow = outputSheet.getLastRowNum(); int startingRow = outputSheet.getLastRowNum();
HSSFRow row = outputSheet.createRow(++startingRow); HSSFRow row = outputSheet.createRow(++startingRow);
int cellnum = 0; int cellnum = 0;
HSSFCell cell = row.createCell(cellnum++); HSSFCell cell = row.createCell(cellnum++);
cell.setCellValue("Iteration"); cell.setCellValue("Iteration");
//Create a section for every camera
for(int i = 0; i < camCount; i++) for(int i = 0; i < camCount; i++)
{ {
cell = row.createCell(cellnum++); cell = row.createCell(cellnum++);
@ -153,7 +147,6 @@ public class DataSaving
HSSFCell passPercentCell = row.createCell(cellnum++); HSSFCell passPercentCell = row.createCell(cellnum++);
passPercentCell.setCellValue("Pass %"); passPercentCell.setCellValue("Pass %");
//Save to file
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) try (FileOutputStream outputStream = new FileOutputStream(outputFile))
{ outputWorkbook.write(outputStream); } { outputWorkbook.write(outputStream); }
catch(Exception e) {ErrorLogging.logError(e);} catch(Exception e) {ErrorLogging.logError(e);}
@ -175,10 +168,8 @@ public class DataSaving
int serialColumn = lastColumnOfData - 2; int serialColumn = lastColumnOfData - 2;
int percentColumn = lastColumnOfData - 1; int percentColumn = lastColumnOfData - 1;
//Get the last row, add another row below it, and name the first cell "Totals:"
int lastRowOfData = outputSheet.getLastRowNum(); int lastRowOfData = outputSheet.getLastRowNum();
//For each camera, create a unique total line
int column = 1; int column = 1;
for(int i = 0; i < cameraCount; i++) for(int i = 0; i < cameraCount; i++)
{ {
@ -219,7 +210,6 @@ public class DataSaving
column += 4; column += 4;
} }
//Once all totals have been created, write to the file
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) try (FileOutputStream outputStream = new FileOutputStream(outputFile))
{ outputWorkbook.write(outputStream); } { outputWorkbook.write(outputStream); }
catch(Exception e) {ErrorLogging.logError(e);} catch(Exception e) {ErrorLogging.logError(e);}
@ -238,10 +228,8 @@ public class DataSaving
boolean output = false; boolean output = false;
int cellnum = 0; int cellnum = 0;
int startingRow = outputSheet.getLastRowNum(); int startingRow = outputSheet.getLastRowNum();
HSSFRow row = (startingRow == 1) ? outputSheet.getRow(++startingRow) : outputSheet.createRow(++startingRow); HSSFRow row = (cycle == 1) ? outputSheet.getRow(++startingRow) : outputSheet.createRow(++startingRow);
List<String> cameraNames = new ArrayList<>(cameraToFile.keySet()); List<String> cameraNames = new ArrayList<>(cameraToFile.keySet());
//ErrorLogging.logError("DEBUG: image locations: " + imageLocations.toString());
//List<Object> objectArray = new LinkedList<>();
cycle++; cycle++;
@ -249,12 +237,10 @@ public class DataSaving
indexCell.setCellValue(cycle); indexCell.setCellValue(cycle);
for(String cameraName : cameraNames) for(String cameraName : cameraNames)
{ {
//put serial number into sheet
String serialNumber = ConfigFacade.getSerial(cameraName); String serialNumber = ConfigFacade.getSerial(cameraName);
HSSFCell serialCell = row.createCell(cellnum++); HSSFCell serialCell = row.createCell(cellnum++);
serialCell.setCellValue(serialNumber); serialCell.setCellValue(serialNumber);
//Put the generated image into the spreadsheet
File file = cameraToFile.get(cameraName); File file = cameraToFile.get(cameraName);
HSSFCell imageCell = row.createCell(cellnum++); HSSFCell imageCell = row.createCell(cellnum++);
try try

View file

@ -61,10 +61,8 @@ public class ErrorLogging
//Make sure the filename formatter is compatible with Windows and Linux //Make sure the filename formatter is compatible with Windows and Linux
fileDatetime = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss"); fileDatetime = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss");
//Local formatter for logs
datetime = DateTimeFormatter.ISO_LOCAL_DATE_TIME; datetime = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//Create a new log file on every run; put them all in a common folder
logFile = "logs/" + fileDatetime.format(LocalDateTime.now()) + "-log.txt"; logFile = "logs/" + fileDatetime.format(LocalDateTime.now()) + "-log.txt";
File logDirectory = new File("logs"); File logDirectory = new File("logs");
File outFile = new File(logFile); File outFile = new File(logFile);

View file

@ -20,7 +20,7 @@ import com.pi4j.io.pwm.PwmType;
* Currently missing Run switch compatibility. * Currently missing Run switch compatibility.
* *
* @author Blizzard Finnegan * @author Blizzard Finnegan
* @version 3.0.0, 06 Mar. 2023 * @version 3.0.1, 10 Mar. 2023
*/ */
public class MovementFacade public class MovementFacade
{ {
@ -190,7 +190,7 @@ public class MovementFacade
static static
{ {
//ErrorLogging.logError("DEBUG: Starting lock thread..."); ErrorLogging.logError("DEBUG: Starting lock thread...");
runSwitchThread = new Thread(() -> runSwitchThread = new Thread(() ->
{ {
boolean unlock = false; boolean unlock = false;
@ -198,7 +198,7 @@ public class MovementFacade
{ {
if(runSwitch.isOn()) if(runSwitch.isOn())
{ {
ErrorLogging.logError("Run switch turned off!"); ErrorLogging.logError("DEBUG: Run switch turned off!");
while(!Cli.LOCK.tryLock()) while(!Cli.LOCK.tryLock())
{} {}
unlock = true; unlock = true;
@ -214,24 +214,19 @@ public class MovementFacade
}, "Run switch monitor."); }, "Run switch monitor.");
runSwitchThread.start(); runSwitchThread.start();
//Initialise Pi4J
pi4j = Pi4J.newAutoContext(); pi4j = Pi4J.newAutoContext();
//Initialise input pins
upperLimit = inputBuilder("upperLimit", "Upper Limit Switch", UPPER_LIMIT_ADDR); upperLimit = inputBuilder("upperLimit", "Upper Limit Switch", UPPER_LIMIT_ADDR);
lowerLimit = inputBuilder("lowerLimit", "Lower Limit Switch", LOWER_LIMIT_ADDR); lowerLimit = inputBuilder("lowerLimit", "Lower Limit Switch", LOWER_LIMIT_ADDR);
runSwitch = inputBuilder("runSwitch" , "Run Switch" , RUN_SWITCH_ADDR); runSwitch = inputBuilder("runSwitch" , "Run Switch" , RUN_SWITCH_ADDR);
//Initialise output pins
motorEnable = outputBuilder("motorEnable" , "Motor Enable" , MOTOR_ENABLE_ADDR); motorEnable = outputBuilder("motorEnable" , "Motor Enable" , MOTOR_ENABLE_ADDR);
motorDirection = outputBuilder("motorDirection", "Motor Direction", MOTOR_DIRECTION_ADDR); motorDirection = outputBuilder("motorDirection", "Motor Direction", MOTOR_DIRECTION_ADDR);
pistonActivate = outputBuilder("piston" , "Piston Activate", PISTON_ADDR); pistonActivate = outputBuilder("piston" , "Piston Activate", PISTON_ADDR);
//Initialise PWM object.
pwm = pwmBuilder("pwm","PWM Pin",PWM_PIN_ADDR); pwm = pwmBuilder("pwm","PWM Pin",PWM_PIN_ADDR);
pwm.on(DUTY_CYCLE, FREQUENCY); pwm.on(DUTY_CYCLE, FREQUENCY);
//Find Distance and max speeds
calibrate(); calibrate();
} }
@ -267,7 +262,6 @@ public class MovementFacade
.frequency(FREQUENCY) .frequency(FREQUENCY)
.provider("pigpio-pwm") .provider("pigpio-pwm")
.initial(1) .initial(1)
//On program close, turn off PWM.
.shutdown(0); .shutdown(0);
break; break;
//Any pin not listed above must be software PWM controlled. //Any pin not listed above must be software PWM controlled.
@ -280,7 +274,6 @@ public class MovementFacade
.frequency(FREQUENCY) .frequency(FREQUENCY)
.provider("pigpio-pwm") .provider("pigpio-pwm")
.initial(1) .initial(1)
//On program close, turn off PWM.
.shutdown(0); .shutdown(0);
} }
return pi4j.create(configBuilder); return pi4j.create(configBuilder);
@ -299,7 +292,6 @@ public class MovementFacade
{ {
DigitalInputConfigBuilder configBuilder = DigitalInput.newConfigBuilder(pi4j) DigitalInputConfigBuilder configBuilder = DigitalInput.newConfigBuilder(pi4j)
.id(id) .id(id)
//.name(name)
.address(address) .address(address)
.pull(PullResistance.PULL_DOWN) .pull(PullResistance.PULL_DOWN)
.debounce(3000L) .debounce(3000L)
@ -320,7 +312,6 @@ public class MovementFacade
{ {
DigitalOutputConfigBuilder configBuilder = DigitalOutput.newConfigBuilder(pi4j) DigitalOutputConfigBuilder configBuilder = DigitalOutput.newConfigBuilder(pi4j)
.id(id) .id(id)
.name(name)
.address(address) .address(address)
.shutdown(DigitalState.LOW) .shutdown(DigitalState.LOW)
.initial(DigitalState.LOW) .initial(DigitalState.LOW)
@ -382,8 +373,6 @@ public class MovementFacade
resetArm(); resetArm();
ErrorLogging.logError("Calibrating..."); ErrorLogging.logError("Calibrating...");
FREQUENCY = calib(MIN_FREQUENCY, MAX_FREQUENCY, 10000); FREQUENCY = calib(MIN_FREQUENCY, MAX_FREQUENCY, 10000);
//ErrorLogging.logError("Fine calibrating...");
//FREQUENCY = calib(FREQUENCY,(FREQUENCY+10000),1000);
ErrorLogging.logError("Calibration complete!"); ErrorLogging.logError("Calibration complete!");
ErrorLogging.logError("DEBUG: Speed set to " + (FREQUENCY - SPEED_BUFFER)); ErrorLogging.logError("DEBUG: Speed set to " + (FREQUENCY - SPEED_BUFFER));
setFrequency(FREQUENCY - SPEED_BUFFER); setFrequency(FREQUENCY - SPEED_BUFFER);
@ -454,7 +443,6 @@ public class MovementFacade
*/ */
private static int calib(int start, int max, int iterate) private static int calib(int start, int max, int iterate)
{ {
//start -= iterate;
for(int i = start; i < max; i+=iterate) for(int i = start; i < max; i+=iterate)
{ {
if(!setFrequency(i)) if(!setFrequency(i))
@ -467,7 +455,7 @@ public class MovementFacade
ErrorLogging.logError("DEBUG: Motor Frequency: " + FREQUENCY); ErrorLogging.logError("DEBUG: Motor Frequency: " + FREQUENCY);
ErrorLogging.logError("DEBUG: Motor calibrate on."); ErrorLogging.logError("DEBUG: Motor calibrate on.");
motorEnable.on(); motorEnable.on();
int TWO_SECONDS = 2 * TIME_CONVERSION; int TWO_SECONDS = 20 * TIME_CONVERSION;
for(int j = 0; j < TWO_SECONDS; j++) for(int j = 0; j < TWO_SECONDS; j++)
{ {
try{ Thread.sleep(POLL_WAIT); } catch(Exception e){ ErrorLogging.logError(e); } try{ Thread.sleep(POLL_WAIT); } catch(Exception e){ ErrorLogging.logError(e); }

View file

@ -27,7 +27,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.io.File; import java.io.File;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -37,11 +36,10 @@ import java.util.List;
* Performs image capture, as well as image manipulation. * Performs image capture, as well as image manipulation.
* *
* @author Blizzard Finnegan * @author Blizzard Finnegan
* @version 2.1.0, 06 Mar. 2023 * @version 3.0.0, 10 Mar. 2023
*/ */
public class OpenCVFacade public class OpenCVFacade
{ {
//Local variable instantiation
/** /**
* Storage of all cameras as Map. * Storage of all cameras as Map.
* To get available camera names, getKeys. * To get available camera names, getKeys.
@ -51,7 +49,7 @@ public class OpenCVFacade
/** /**
* Object used to convert between Mats and Frames * Object used to convert between Mats and Frames
*/ */
public static final OpenCVFrameConverter.ToMat MAT_CONVERTER = new OpenCVFrameConverter.ToMat(); private static final OpenCVFrameConverter.ToMat MAT_CONVERTER = new OpenCVFrameConverter.ToMat();
/** /**
* Width of the image created by the camera. * Width of the image created by the camera.
@ -129,7 +127,6 @@ public class OpenCVFacade
*/ */
private static void newCamera(String name, String location, int width, int height, String codec) private static void newCamera(String name, String location, int width, int height, String codec)
{ {
//ErrorLogging.logError("DEBUG: Attempting to create new camera " + name + " from location " + location + "...");
ErrorLogging.logError("Initialising camera : " + name + "..."); ErrorLogging.logError("Initialising camera : " + name + "...");
File cameraLocation = new File(location); File cameraLocation = new File(location);
if (cameraLocation.exists()) if (cameraLocation.exists())
@ -171,7 +168,7 @@ public class OpenCVFacade
* @return null if camera doesn't exist, or if capture fails; * @return null if camera doesn't exist, or if capture fails;
* otherwise, Frame of the taken image * otherwise, Frame of the taken image
*/ */
public static Mat takePicture(String cameraName) private static Mat takePicture(String cameraName)
{ {
Mat output = null; Mat output = null;
Frame temp = null; Frame temp = null;
@ -199,12 +196,8 @@ public class OpenCVFacade
*/ */
public static File showImage(String cameraName) public static File showImage(String cameraName)
{ {
//ErrorLogging.logError("DEBUG: Showing image from camera: " + cameraName);
//ErrorLogging.logError("DEBUG: camera location: " + cameraMap.get(cameraName).toString());
File imageLocation = completeProcess(cameraName,ConfigFacade.getImgSaveLocation() + "/config"); File imageLocation = completeProcess(cameraName,ConfigFacade.getImgSaveLocation() + "/config");
if(imageLocation == null) return null; if(imageLocation == null) return null;
//ErrorLogging.logError("DEBUG: Image processed successfully.");
//ErrorLogging.logError("DEBUG: Image location: " + imageLocation.getAbsolutePath());
Frame outputImage = MAT_CONVERTER.convert(imread(imageLocation.getAbsolutePath())); Frame outputImage = MAT_CONVERTER.convert(imread(imageLocation.getAbsolutePath()));
String canvasTitle = "Camera " + cameraName + " Preview"; String canvasTitle = "Camera " + cameraName + " Preview";
final CanvasFrame canvas = new CanvasFrame(canvasTitle); final CanvasFrame canvas = new CanvasFrame(canvasTitle);
@ -212,20 +205,18 @@ public class OpenCVFacade
return imageLocation; return imageLocation;
} }
/** ///**
* Show current processed image to the GUI user. // * Show current processed image to the GUI user.
* // *
* @param cameraName The name of the camera to be previewed // * @param cameraName The name of the camera to be previewed
* // *
* @return The {@link CanvasFrame} that is being opened. This is returned so it can be closed by the program. // * @return The {@link CanvasFrame} that is being opened. This is returned so it can be closed by the program.
*/ // */
public static String showImage(String cameraName, Object object) //private static String showImage(String cameraName, Object object)
{ //{
//ErrorLogging.logError("DEBUG: Showing image from camera: " + cameraName); // File imageLocation = completeProcess(cameraName,ConfigFacade.getImgSaveLocation() + "/config");
//ErrorLogging.logError("DEBUG: camera location: " + cameraMap.get(cameraName).toString()); // return imageLocation.getPath();
File imageLocation = completeProcess(cameraName,ConfigFacade.getImgSaveLocation() + "/config"); //}
return imageLocation.getPath();
}
/** /**
* Take multiple pictures in quick succession. * Take multiple pictures in quick succession.
@ -235,11 +226,9 @@ public class OpenCVFacade
* *
* @return List of Frames taken from the camera. List is in order * @return List of Frames taken from the camera. List is in order
*/ */
public static List<Mat> takeBurst(String cameraName, int frameCount) private static List<Mat> takeBurst(String cameraName, int frameCount)
{ {
List<Mat> output = null; List<Mat> output = null;
//ErrorLogging.logError("DEBUG: takeBurst - Camera Name: " + cameraName);
//ErrorLogging.logError("DEBUG: takeBurst - Possible camera names: " + getCameraNames().toString());
if(getCameraNames().contains(cameraName)) if(getCameraNames().contains(cameraName))
{ {
output = new LinkedList<>(); output = new LinkedList<>();
@ -272,7 +261,7 @@ public class OpenCVFacade
* @param image Frame taken from the camera * @param image Frame taken from the camera
* @param cameraName Name of the camera the frame is from * @param cameraName Name of the camera the frame is from
*/ */
public static Mat crop(Mat image, String cameraName) private static Mat crop(Mat image, String cameraName)
{ {
int x = (int)ConfigFacade.getValue(cameraName,ConfigProperties.CROP_X); int x = (int)ConfigFacade.getValue(cameraName,ConfigProperties.CROP_X);
int y = (int)ConfigFacade.getValue(cameraName,ConfigProperties.CROP_Y); int y = (int)ConfigFacade.getValue(cameraName,ConfigProperties.CROP_Y);
@ -290,15 +279,9 @@ public class OpenCVFacade
* *
* @return Frame of the cropped image * @return Frame of the cropped image
*/ */
public static Mat crop(Mat image, Rect roi, String cameraName) private static Mat crop(Mat image, Rect roi, String cameraName)
{ {
Mat output = image.apply(roi).clone(); Mat output = image.apply(roi).clone();
//IplImage croppedImage = MAT_CONVERTER.convertToIplImage(MAT_CONVERTER.convert(output));
//String fileLocation = ConfigFacade.getImgSaveLocation() + "/debug/"
// + ErrorLogging.fileDatetime.format(LocalDateTime.now()) +
// "." + cameraName + "-preProcess.jpg";
//cvSaveImage(fileLocation,croppedImage);
return output; return output;
} }
@ -311,7 +294,7 @@ public class OpenCVFacade
* *
* @return Frame of the thresholded image * @return Frame of the thresholded image
*/ */
public static Mat thresholdImage(Mat image,String cameraName) private static Mat thresholdImage(Mat image,String cameraName)
{ {
Mat output = image; Mat output = image;
Mat in = image; Mat in = image;
@ -328,7 +311,7 @@ public class OpenCVFacade
* *
* @return File if save was successful, otherwise null * @return File if save was successful, otherwise null
*/ */
public static File saveImage(Mat image, String fileLocation, String cameraName) private static File saveImage(Mat image, String fileLocation, String cameraName)
{ {
File output = null; File output = null;
IplImage temp = MAT_CONVERTER.convertToIplImage(MAT_CONVERTER.convert(image)); IplImage temp = MAT_CONVERTER.convertToIplImage(MAT_CONVERTER.convert(image));
@ -350,64 +333,32 @@ public class OpenCVFacade
* *
* @return A single image, found by boolean AND-ing together all parsed images. * @return A single image, found by boolean AND-ing together all parsed images.
*/ */
public static Mat compose(List<Mat> images, boolean threshold, private static Mat compose(List<Mat> images, boolean threshold,
boolean crop, String cameraName) boolean crop, String cameraName)
{ {
ErrorLogging.logError("DEBUG: Attempting to compose " + images.size() + " images..."); ErrorLogging.logError("DEBUG: Attempting to compose " + images.size() + " images...");
Mat output = null; Mat output = null;
int iterationCount = 1; int iterationCount = 1;
for(Mat image : images) for(Mat image : images)
{ //crop and threshold, based on booleans {
Mat processedImage = image.clone(); Mat processedImage = image.clone();
image.copyTo(processedImage); image.copyTo(processedImage);
if(crop) if(crop) processedImage = crop(processedImage,cameraName);
{ if(threshold) processedImage = thresholdImage(processedImage,cameraName);
//ErrorLogging.logError("DEBUG: Cropping image " + iterationCount + "...");
processedImage = crop(processedImage,cameraName); if(iterationCount == 1) output = processedImage.clone();
//String fileLocation = ConfigFacade.getImgSaveLocation() + "/debug/"
// + ErrorLogging.fileDatetime.format(LocalDateTime.now()) +
// "." + iterationCount + "-post-crop.jpg";
//cvSaveImage(fileLocation,MAT_CONVERTER.convertToIplImage(
// MAT_CONVERTER.convert(processedImage)));
}
if(threshold)
{
//ErrorLogging.logError("DEBUG: Thresholding image " + iterationCount + "...");
processedImage = thresholdImage(processedImage,cameraName);
//String fileLocation = ConfigFacade.getImgSaveLocation() + "/debug/"
// + ErrorLogging.fileDatetime.format(LocalDateTime.now()) +
// "." + iterationCount + "-post-threshold.jpg";
//cvSaveImage(fileLocation,MAT_CONVERTER.convertToIplImage(
// MAT_CONVERTER.convert(processedImage)));
}
//String fileLocation = ConfigFacade.getImgSaveLocation() + "/debug/"
// + ErrorLogging.fileDatetime.format(LocalDateTime.now()) +
// "." + iterationCount + "-pre.compose.jpg";
//cvSaveImage(fileLocation,MAT_CONVERTER.convertToIplImage(
// MAT_CONVERTER.convert(processedImage)));
//ErrorLogging.logError("DEBUG: Post-threshold/crop image: " + fileLocation);
//ErrorLogging.logError("DEBUG: Image " + iterationCount + " complete!");
//ErrorLogging.logError("DEBUG: -----------------");
//ErrorLogging.logError("DEBUG: Post-threshold/crop width: " + processedImage.cols());
if(iterationCount == 1)
{
output = processedImage.clone();
}
//ErrorLogging.logError("DEBUG: Thresholding image " + iterationCount + "...");
bitwise_and((iterationCount == 1 ? processedImage : output),processedImage, output); bitwise_and((iterationCount == 1 ? processedImage : output),processedImage, output);
iterationCount++; iterationCount++;
} }
if(output != null) if(output != null) ErrorLogging.logError("DEBUG: Compositing successful!");
ErrorLogging.logError("DEBUG: Compositing successful!"); else ErrorLogging.logError("ERROR: Final output image is null!");
else
ErrorLogging.logError("ERROR: Final output image is null!");
return output; return output;
} }
/**TODO: More robust file output checking; /**
* Processes image from defined camera, using the config defaults. * Processes image from defined camera, using the config defaults.
* *
* *
@ -429,18 +380,8 @@ public class OpenCVFacade
ErrorLogging.logError("OPENCV ERROR!!! - Invalid camera name."); ErrorLogging.logError("OPENCV ERROR!!! - Invalid camera name.");
return output; return output;
} }
//ErrorLogging.logError("DEBUG: Camera to take picture from: " + cameraName);
//ErrorLogging.logError("DEBUG: Composite frame count: " + compositeFrames);
List<Mat> imageList = takeBurst(cameraName, compositeFrames); List<Mat> imageList = takeBurst(cameraName, compositeFrames);
//Debug save of pre-processing image
//String fileLocation = ConfigFacade.getImgSaveLocation() + "/debug/"
// + ErrorLogging.fileDatetime.format(LocalDateTime.now()) +
// "." + cameraName + "-preProcess.jpg";
//cvSaveImage(fileLocation,MAT_CONVERTER.convertToIplImage(
// MAT_CONVERTER.convert(imageList.get(0))));
ErrorLogging.logError("DEBUG: Size of output image list: " + imageList.size());
Mat finalImage = compose(imageList, threshold, crop, cameraName); Mat finalImage = compose(imageList, threshold, crop, cameraName);
output = saveImage(finalImage, saveLocation,cameraName); output = saveImage(finalImage, saveLocation,cameraName);
return output; return output;
@ -458,21 +399,21 @@ public class OpenCVFacade
public static File completeProcess(String cameraName, String saveLocation) public static File completeProcess(String cameraName, String saveLocation)
{ {
File output = null; File output = null;
if(!getCameraNames().contains(cameraName)) if(!getCameraNames().contains(cameraName))
{ {
ErrorLogging.logError("OPENCV ERROR!!! - Invalid camera name."); ErrorLogging.logError("OPENCV ERROR!!! - Invalid camera name.");
return output; return output;
} }
int compositeFrames = (int)ConfigFacade.getValue(cameraName,ConfigProperties.COMPOSITE_FRAMES); int compositeFrames = (int)ConfigFacade.getValue(cameraName,ConfigProperties.COMPOSITE_FRAMES);
//boolean threshold = false;
boolean threshold = (ConfigFacade.getValue(cameraName,ConfigProperties.THRESHOLD) != 0.0); boolean threshold = (ConfigFacade.getValue(cameraName,ConfigProperties.THRESHOLD) != 0.0);
//ErrorLogging.logError("DEBUG: Threshold config value: " + threshold);
//boolean crop = false;
boolean crop = (ConfigFacade.getValue(cameraName,ConfigProperties.CROP) != 0.0); boolean crop = (ConfigFacade.getValue(cameraName,ConfigProperties.CROP) != 0.0);
//ErrorLogging.logError("DEBUG: Crop config value: " + crop);
output = completeProcess(cameraName,crop,threshold,compositeFrames,saveLocation); output = completeProcess(cameraName,crop,threshold,compositeFrames,saveLocation);
if(output == null)
ErrorLogging.logError("OPENCV ERROR!!!: Final processed image is null!"); if(output == null) ErrorLogging.logError("OPENCV ERROR!!!: Final processed image is null!");
return output; return output;
} }
@ -485,23 +426,5 @@ public class OpenCVFacade
* @return null if any error occurs; otherwise File of output image * @return null if any error occurs; otherwise File of output image
*/ */
public static File completeProcess(String cameraName) public static File completeProcess(String cameraName)
{ { return completeProcess(cameraName,ConfigFacade.getImgSaveLocation()); }
return completeProcess(cameraName,ConfigFacade.getImgSaveLocation());
}
/**
* Collect images from all cameras and save them, using the config defaults.
*
* @return List of Files, as defined by {@code #completeProcess(String, String)}
*/
public static List<File> singleIteration()
{
List<File> output = new ArrayList<>();
for(String cameraName : getCameraNames())
{
output.add(completeProcess(cameraName, ConfigFacade.getImgSaveLocation()));
ErrorLogging.logError("DEBUG: ---------------------------------");
}
return output;
}
} }

View file

@ -69,23 +69,16 @@ public class TesseractFacade
*/ */
public static double imageToDouble(File file) public static double imageToDouble(File file)
{ {
//Set default output
double output = Double.NEGATIVE_INFINITY; double output = Double.NEGATIVE_INFINITY;
//Import image, parse image
PIX importedImage = pixRead(file.getAbsolutePath()); PIX importedImage = pixRead(file.getAbsolutePath());
api.SetImage(importedImage); api.SetImage(importedImage);
String stringOutput = api.GetUTF8Text().getString(); String stringOutput = api.GetUTF8Text().getString();
//Determine whether the OCR output is actually a double
if(!stringOutput.isEmpty()) if(!stringOutput.isEmpty())
{ {
try(Scanner sc = new Scanner(stringOutput.trim());) try( Scanner sc = new Scanner(stringOutput.trim()); )
{ {
/*
* Discos have error messages (LO, HI, POS, ?). Consider parsing as well.
* Update on above note: Requires retraining Tesseract
*/
if(sc.hasNextDouble()) if(sc.hasNextDouble())
{ {
output = sc.nextDouble(); output = sc.nextDouble();
@ -98,19 +91,14 @@ public class TesseractFacade
output = output / 10; output = output / 10;
ErrorLogging.logError("OCR output saved, as value appears to be real. Value needs to be verified."); ErrorLogging.logError("OCR output saved, as value appears to be real. Value needs to be verified.");
} }
else if(output >= 200) else if(output >= 200) ErrorLogging.logError("OCR WARNING - OCR output is too high for DUT, potential misread.");
ErrorLogging.logError("OCR WARNING - OCR output is too high for DUT, potential misread."); else ErrorLogging.logError("OCR output successfully adjusted. Disregard warning.");
else
ErrorLogging.logError("OCR output successfully adjusted. Disregard warning.");
} }
if(output <= -10) if(output <= -10) ErrorLogging.logError("OCR ERROR!!! - OCR output is too low for DUT, potential misread.");
ErrorLogging.logError("OCR ERROR!!! - OCR output is too low for DUT, potential misread.");
} }
else ErrorLogging.logError("OCR ERROR!!! - OCR output is not a Double."); else ErrorLogging.logError("OCR ERROR!!! - OCR output is not a Double.");
} }
} }
//Return output
return output; return output;
} }
} }