v4.3.6 push #15
9 changed files with 70 additions and 294 deletions
|
@ -4,7 +4,7 @@
|
|||
<groupId>org.baxter.disco</groupId>
|
||||
<artifactId>ocr</artifactId>
|
||||
<name>Disco OCR Accuracy Over Life Testing</name>
|
||||
<version>4.3.5</version>
|
||||
<version>4.3.6</version>
|
||||
<description>Testing Discos for long-term accuracy, using automated optical character recognition.</description>
|
||||
<organization>
|
||||
<name>Baxter International</name>
|
||||
|
@ -91,9 +91,6 @@
|
|||
<plugin>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
|
38
pom.xml
38
pom.xml
|
@ -3,7 +3,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baxter.disco</groupId>
|
||||
<artifactId>ocr</artifactId>
|
||||
<version>4.3.5</version>
|
||||
<version>4.3.6</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>Disco OCR Accuracy Over Life Testing</name>
|
||||
<description>Testing Discos for long-term accuracy, using automated optical character recognition.</description>
|
||||
|
@ -47,7 +47,6 @@
|
|||
<artifactId>javacv-platform</artifactId>
|
||||
<version>${opencv.version}</version>
|
||||
</dependency>
|
||||
<!-- So... turns out, the showImage call requires JavaFX Swing, but doesn't actually *say* it requires that. -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-swing</artifactId>
|
||||
|
@ -91,13 +90,6 @@
|
|||
<artifactId>pi4j-plugin-pigpio</artifactId>
|
||||
<version>${pi4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JavaFX Import -->
|
||||
<!--<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
</dependency>-->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -184,30 +176,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</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>
|
||||
</build>
|
||||
<reporting>
|
||||
|
@ -216,9 +184,9 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<!--<configuration>
|
||||
<show>private</show>
|
||||
</configuration>
|
||||
</configuration> -->
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
|
|
@ -18,14 +18,14 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||
* classes).
|
||||
*
|
||||
* @author Blizzard Finnegan
|
||||
* @version 1.7.0, 06 Mar. 2023
|
||||
* @version 1.7.1, 10 Mar. 2023
|
||||
*/
|
||||
public class Cli
|
||||
{
|
||||
/**
|
||||
* Complete build version number
|
||||
*/
|
||||
private static final String version = "4.3.5";
|
||||
private static final String version = "4.3.6";
|
||||
|
||||
/**
|
||||
* Currently saved iteration count.
|
||||
|
@ -65,12 +65,10 @@ public class Cli
|
|||
*/
|
||||
public static final Lock LOCK = new ReentrantLock();
|
||||
|
||||
//private static Thread safeThread;
|
||||
|
||||
//Start of program message; always runs first
|
||||
static
|
||||
{
|
||||
ErrorLogging.logError("START OF PROGRAM");
|
||||
ErrorLogging.logError("DEBUG: START OF PROGRAM");
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
|
@ -354,13 +352,10 @@ public class Cli
|
|||
MovementFacade.iterationMovement(true);
|
||||
double tesseractValue = 0.0;
|
||||
|
||||
//Main camera config loop
|
||||
do
|
||||
{
|
||||
//Show the menu
|
||||
printCameraMenu(cameraList);
|
||||
|
||||
//Pick a camera to configure
|
||||
int userInput;
|
||||
String cameraName = "";
|
||||
do
|
||||
|
@ -370,12 +365,10 @@ public class Cli
|
|||
userInput--;
|
||||
} while (cameraList.size() < userInput && userInput < 0);
|
||||
|
||||
//Leave do-while loop if the user asks to
|
||||
if(userInput == (cameraList.size())) break;
|
||||
else if(userInput < 0) continue;
|
||||
else cameraName = cameraList.get((userInput));
|
||||
|
||||
//Single camera config loop
|
||||
do
|
||||
{
|
||||
//Press button twice, to make sure the DUT is awake
|
||||
|
@ -384,17 +377,12 @@ public class Cli
|
|||
MovementFacade.pressButton();
|
||||
try{ Thread.sleep(2000); } catch(Exception e){ ErrorLogging.logError(e); }
|
||||
|
||||
//Show image
|
||||
File image = OpenCVFacade.showImage(cameraName);
|
||||
|
||||
//Parse the image with Tesseract, to show user what the excel output will be
|
||||
tesseractValue = TesseractFacade.imageToDouble(image);
|
||||
|
||||
//User input parsing
|
||||
ConfigProperties modifiedProperty = null;
|
||||
do
|
||||
{
|
||||
//list configurable settings
|
||||
printCameraConfigMenu(cameraName,tesseractValue);
|
||||
|
||||
userInput = (int)inputFiltering(inputScanner.nextLine(),Menus.CAMERA);
|
||||
|
@ -422,7 +410,6 @@ public class Cli
|
|||
}
|
||||
} while(modifiedProperty == null);
|
||||
|
||||
//Toggle threshold/crop
|
||||
if(modifiedProperty == ConfigProperties.THRESHOLD ||
|
||||
modifiedProperty == ConfigProperties.CROP)
|
||||
{
|
||||
|
@ -431,11 +418,9 @@ public class Cli
|
|||
ConfigFacade.setValue(cameraName,modifiedProperty,newValue);
|
||||
}
|
||||
|
||||
//Redefine crop points
|
||||
else if(modifiedProperty == ConfigProperties.CROP_X)
|
||||
{ OpenCVFacade.setCrop(cameraName); }
|
||||
|
||||
//Modify number of composite frames, or threshold value
|
||||
else if(modifiedProperty == ConfigProperties.COMPOSITE_FRAMES ||
|
||||
modifiedProperty == ConfigProperties.THRESHOLD_VALUE)
|
||||
{
|
||||
|
@ -447,7 +432,6 @@ public class Cli
|
|||
ConfigFacade.setValue(cameraName,modifiedProperty,userInput);
|
||||
}
|
||||
|
||||
//Exit loop
|
||||
else
|
||||
{
|
||||
ConfigFacade.saveCurrentConfig();
|
||||
|
@ -457,7 +441,6 @@ public class Cli
|
|||
|
||||
} while(true);
|
||||
|
||||
//Save the current config to the config file
|
||||
ConfigFacade.saveCurrentConfig();
|
||||
println("Configuration complete!");
|
||||
}
|
||||
|
@ -467,15 +450,11 @@ public class Cli
|
|||
*/
|
||||
private static void setDUTSerials()
|
||||
{
|
||||
//Get a list of available cameras
|
||||
List<String> cameraList = new ArrayList<>(OpenCVFacade.getCameraNames());
|
||||
//Main serial setting loop
|
||||
do
|
||||
{
|
||||
//Main menu
|
||||
printSerialMenu(cameraList);
|
||||
|
||||
//Pick a camera to configure
|
||||
int userInput;
|
||||
String cameraName = "";
|
||||
do
|
||||
|
@ -486,12 +465,9 @@ public class Cli
|
|||
userInput--;
|
||||
} while (cameraList.size() < userInput || userInput < 0);
|
||||
|
||||
//Leave do-while loop if the user asks to
|
||||
if(userInput == (cameraList.size())) break;
|
||||
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: ");
|
||||
ConfigFacade.setSerial(cameraName,inputScanner.nextLine());
|
||||
|
||||
|
@ -518,16 +494,12 @@ public class Cli
|
|||
*/
|
||||
private static void setActiveCameras()
|
||||
{
|
||||
//Get available cameras
|
||||
List<String> cameraList = new ArrayList<>(OpenCVFacade.getCameraNames());
|
||||
|
||||
//Main loop
|
||||
do
|
||||
{
|
||||
//Print menu
|
||||
printActiveToggleMenu(cameraList);
|
||||
|
||||
//Pick a camera to configure
|
||||
int userInput;
|
||||
String cameraName = "";
|
||||
do
|
||||
|
@ -537,11 +509,9 @@ public class Cli
|
|||
userInput--;
|
||||
} while (cameraList.size() < userInput || userInput < 0);
|
||||
|
||||
//Leave do-while loop if the user asks to
|
||||
if(userInput == (cameraList.size())) break;
|
||||
else cameraName = cameraList.get((userInput));
|
||||
|
||||
//Toggle whether the camera is active, at the config level
|
||||
double newValue = ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE);
|
||||
newValue = Math.abs(newValue - 1);
|
||||
ConfigFacade.setValue(cameraName,ConfigProperties.ACTIVE,newValue);
|
||||
|
@ -561,22 +531,18 @@ public class Cli
|
|||
//useful for multithreading, which isn't necessary in CLI
|
||||
final int localIterations = iterationCount;
|
||||
|
||||
//Save whether to prime the devices; defaults to false
|
||||
//Hide legacy functionality
|
||||
boolean prime = false;
|
||||
|
||||
//Create a List of *active* cameras.
|
||||
List<String> cameraList = new ArrayList<>();
|
||||
for(String cameraName : OpenCVFacade.getCameraNames())
|
||||
{
|
||||
prime = (ConfigFacade.getValue(cameraName,ConfigProperties.PRIME) != 0) || prime;
|
||||
|
||||
if(ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE) != 0)
|
||||
{
|
||||
cameraList.add(cameraName);
|
||||
}
|
||||
}
|
||||
|
||||
//Initialise the workbook, with the number of cameras and the final output location
|
||||
DataSaving.initWorkbook(ConfigFacade.getOutputSaveLocation(),cameraList.size());
|
||||
|
||||
//Wake the device, then wait to ensure they're awake before continuing
|
||||
|
@ -584,7 +550,6 @@ public class Cli
|
|||
MovementFacade.pressButton();
|
||||
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<String,File> cameraToFile = new HashMap<>();
|
||||
|
||||
|
@ -595,7 +560,7 @@ public class Cli
|
|||
}
|
||||
|
||||
ErrorLogging.logError("DEBUG: Starting tests...");
|
||||
//Start actually running tests
|
||||
|
||||
//All portions of the test check with the GPIO Run/Pause switch before
|
||||
//continuing, using the Lock object.
|
||||
for(int i = 0; i < localIterations; i++)
|
||||
|
@ -611,7 +576,6 @@ public class Cli
|
|||
do
|
||||
{
|
||||
fail = false;
|
||||
//Move the fixture for one iteration, with whether or not the DUTs need to be primed
|
||||
while(!LOCK.tryLock()) {}
|
||||
MovementFacade.iterationMovement(prime);
|
||||
LOCK.unlock();
|
||||
|
@ -619,9 +583,6 @@ public class Cli
|
|||
//Wait for the DUT to display an image
|
||||
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)
|
||||
{
|
||||
while(!LOCK.tryLock()) {}
|
||||
|
@ -633,9 +594,6 @@ public class Cli
|
|||
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)
|
||||
{
|
||||
while(!LOCK.tryLock()) {}
|
||||
|
@ -666,16 +624,13 @@ public class Cli
|
|||
}
|
||||
while(fail);
|
||||
|
||||
//Write all given values to the Excel file
|
||||
while(!LOCK.tryLock()) {}
|
||||
DataSaving.writeValues(i,resultMap,cameraToFile);
|
||||
LOCK.unlock();
|
||||
|
||||
//Clear the result map
|
||||
//DO NOT CLEAR camera to file Map. This will change the order of the objects within it
|
||||
resultMap.clear();
|
||||
}
|
||||
//Alert the user to testing being complete
|
||||
println("=======================================");
|
||||
println("Testing complete!");
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.apache.commons.configuration2.builder.fluent.Parameters;
|
|||
* Can write to file when requested, reads from file on initial start.
|
||||
*
|
||||
* @author Blizzard Finnegan
|
||||
* @version 1.3.1, 09 Feb. 2023
|
||||
* @version 1.3.2, 10 Mar. 2023
|
||||
*/
|
||||
public class ConfigFacade
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ public class ConfigFacade
|
|||
/**
|
||||
* Location to save output XLSX file to.
|
||||
*/
|
||||
public static String outputSaveLocation = "outputData/" +
|
||||
private static String outputSaveLocation = "outputData/" +
|
||||
(LocalDateTime.now().format(ErrorLogging.fileDatetime)) + ".xlsx";
|
||||
|
||||
/**
|
||||
|
@ -73,16 +73,14 @@ public class ConfigFacade
|
|||
*/
|
||||
private static INIConfiguration CONFIG_STORE;
|
||||
|
||||
//This block will ALWAYS run first.
|
||||
static
|
||||
{
|
||||
//Get config values
|
||||
ErrorLogging.logError("Starting configuration setup...");
|
||||
//Give CONFIG_STORE an intentionally bad value
|
||||
CONFIG_STORE = null;
|
||||
//See if a config file already exists
|
||||
|
||||
File configFile = new File(configFileLocation);
|
||||
boolean newConfig = true;
|
||||
|
||||
try{ newConfig = configFile.createNewFile(); }
|
||||
catch(Exception e){ ErrorLogging.logError(e); }
|
||||
|
||||
|
@ -90,7 +88,6 @@ public class ConfigFacade
|
|||
CONFIG_BUILDER = new FileBasedConfigurationBuilder<>(INIConfiguration.class)
|
||||
.configure(new Parameters().fileBased().setFile(configFile));
|
||||
|
||||
//Try to import the config
|
||||
ErrorLogging.logError("Attempting to import config...");
|
||||
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
|
||||
{
|
||||
ErrorLogging.logError("Unable to import config. Loading defaults...");
|
||||
|
@ -121,24 +116,19 @@ public class ConfigFacade
|
|||
else ErrorLogging.logError("Configuration settings set up!");
|
||||
}
|
||||
|
||||
//Make necessary directories, if not already available
|
||||
ErrorLogging.logError("Creating image storage directories...");
|
||||
File imageLocation = new File(imageSaveLocation);
|
||||
imageLocation.mkdir();
|
||||
File debugImageLocation = new File(imageSaveLocation + "/debug");
|
||||
debugImageLocation.mkdir();
|
||||
File configImageLocation = new File(imageSaveLocation + "/config");
|
||||
configImageLocation.mkdir();
|
||||
File setupImageLocation = new File(imageSaveLocation + "/config");
|
||||
setupImageLocation.mkdir();
|
||||
File outputFileDirectory = new File("outputData");
|
||||
outputFileDirectory.mkdir();
|
||||
|
||||
//Create a new output file
|
||||
ErrorLogging.logError("Creating output file....");
|
||||
File outputFile = new File(outputSaveLocation);
|
||||
try{ outputFile.createNewFile(); }
|
||||
catch(Exception e){ ErrorLogging.logError(e); }
|
||||
|
||||
//Autosave the config
|
||||
CONFIG_BUILDER.setAutoSave(true);
|
||||
}
|
||||
|
||||
|
@ -161,7 +151,6 @@ public class ConfigFacade
|
|||
double output = 0.0;
|
||||
if(!configMap.keySet().contains(cameraName))
|
||||
{
|
||||
//Log failure information
|
||||
ErrorLogging.logError("CONFIG ERROR!!! - Invalid camera name: " + cameraName);
|
||||
ErrorLogging.logError("\tKey set: " + configMap.keySet().toString());
|
||||
ErrorLogging.logError("\tProperty: " + property.getConfig());
|
||||
|
@ -170,9 +159,6 @@ public class ConfigFacade
|
|||
}
|
||||
Map<ConfigProperties,Double> cameraConfig = configMap.get(cameraName);
|
||||
output = cameraConfig.get(property);
|
||||
//Debug logger.
|
||||
//ErrorLogging.logError("DEBUG: getValue - return value: " + cameraName
|
||||
// + "/" + property.getConfig() + " = " + output);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@ -240,12 +226,16 @@ public class ConfigFacade
|
|||
public static boolean setValue(String cameraName, ConfigProperties property, double propertyValue)
|
||||
{
|
||||
boolean output = false;
|
||||
|
||||
List<String> activeCameras = new ArrayList<>(OpenCVFacade.getCameraNames());
|
||||
if(!activeCameras.contains(cameraName)) return output;
|
||||
|
||||
Map<ConfigProperties,Double> cameraConfig = configMap.get(cameraName);
|
||||
if(cameraConfig == null) return output;
|
||||
|
||||
Double oldValue = cameraConfig.get(property);
|
||||
output = cameraConfig.replace(property,oldValue,propertyValue);
|
||||
|
||||
saveCurrentConfig();
|
||||
return output;
|
||||
}
|
||||
|
@ -288,21 +278,15 @@ public class ConfigFacade
|
|||
*/
|
||||
public static boolean saveDefaultConfig(String filename)
|
||||
{
|
||||
//Get set of camera names
|
||||
boolean output = false;
|
||||
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)
|
||||
.configure(new Parameters().fileBased()
|
||||
.setFile(new File(filename)));
|
||||
|
||||
//Set CONFIG_STORE to the Configuration created by the Builder
|
||||
try { CONFIG_STORE = CONFIG_BUILDER.getConfiguration(); }
|
||||
catch(Exception e) { ErrorLogging.logError(e); }
|
||||
|
||||
//If the save default fails, warn the user that something is wrong
|
||||
finally
|
||||
{
|
||||
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)
|
||||
{
|
||||
Map<ConfigProperties,Double> cameraConfig = new HashMap<>();
|
||||
|
@ -324,14 +304,11 @@ public class ConfigFacade
|
|||
String propertyName = camera + "." + property.getConfig();
|
||||
double propertyValue = property.getDefaultValue();
|
||||
cameraConfig.put(property,propertyValue);
|
||||
//ErrorLogging.logError("DEBUG: Attempting to save to config: ");
|
||||
//ErrorLogging.logError("DEBUG: " + propertyName + ", " + propertyValue);
|
||||
CONFIG_STORE.setProperty(propertyName,propertyValue);
|
||||
}
|
||||
configMap.put(camera,cameraConfig);
|
||||
}
|
||||
|
||||
//Save out to the file
|
||||
try
|
||||
{
|
||||
CONFIG_BUILDER.save();
|
||||
|
@ -442,7 +419,6 @@ public class ConfigFacade
|
|||
for(ConfigProperties configState : ConfigProperties.values())
|
||||
{
|
||||
Double configValue = CONFIG_STORE.getDouble(sectionName + "." + configState.getConfig());
|
||||
//ErrorLogging.logError("DEBUG: Imported config value: " + Double.toString(configValue));
|
||||
savedSection.put(configState,configValue);
|
||||
}
|
||||
}
|
||||
|
@ -456,7 +432,6 @@ public class ConfigFacade
|
|||
{
|
||||
for(String key : configMap.keySet())
|
||||
{
|
||||
//ErrorLogging.logError("DEBUG: configMap Key: " + key + " ?= " + sectionName);
|
||||
if( key.equals(sectionName))
|
||||
{ configMap.put(key,savedSection); }
|
||||
}
|
||||
|
@ -493,8 +468,6 @@ public class ConfigFacade
|
|||
String propertyName = sectionName + "." + property.getConfig();
|
||||
double propertyValue = property.getDefaultValue();
|
||||
cameraConfig.put(property,propertyValue);
|
||||
//ErrorLogging.logError("DEBUG: Attempting to save to config: ");
|
||||
//ErrorLogging.logError("DEBUG: " + propertyName + ", " + propertyValue);
|
||||
CONFIG_STORE.setProperty(propertyName,propertyValue);
|
||||
}
|
||||
configMap.put(sectionName,cameraConfig);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package org.baxter.disco.ocr;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
//Standard imports
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
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.
|
||||
*
|
||||
* @author Blizzard Finnegan
|
||||
* @version 5.0.0, 07 Mar. 2023
|
||||
* @version 5.0.1, 10 Mar. 2023
|
||||
*/
|
||||
public class DataSaving
|
||||
{
|
||||
|
@ -99,16 +99,13 @@ public class DataSaving
|
|||
|
||||
//Create workbook, Sheet, and DataFormat object
|
||||
//HSSF objects are used, as these are compatible with Microsoft Excel
|
||||
//XSSF objects were initially used, but caused issues.
|
||||
outputWorkbook = new HSSFWorkbook();
|
||||
outputSheet = outputWorkbook.createSheet();
|
||||
format = outputWorkbook.createDataFormat();
|
||||
|
||||
//Create a default style for values.
|
||||
defaultStyle = outputWorkbook.createCellStyle();
|
||||
defaultStyle.setDataFormat(format.getFormat("0.0"));
|
||||
|
||||
//Create a style for the final percentage values
|
||||
finalValuesStyle = outputWorkbook.createCellStyle();
|
||||
finalValuesStyle.setDataFormat(format.getFormat("0.000%"));
|
||||
|
||||
|
@ -124,19 +121,16 @@ public class DataSaving
|
|||
failStyle.setDataFormat(format.getFormat("0.0"));
|
||||
failStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
//Create a style for error-ed, but not out-of-range, values
|
||||
errorStyle = outputWorkbook.createCellStyle();
|
||||
errorStyle.setFillForegroundColor(HSSFColorPredefined.YELLOW.getIndex());
|
||||
errorStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
|
||||
//Create the header
|
||||
int startingRow = outputSheet.getLastRowNum();
|
||||
HSSFRow row = outputSheet.createRow(++startingRow);
|
||||
int cellnum = 0;
|
||||
HSSFCell cell = row.createCell(cellnum++);
|
||||
cell.setCellValue("Iteration");
|
||||
//Create a section for every camera
|
||||
for(int i = 0; i < camCount; i++)
|
||||
{
|
||||
cell = row.createCell(cellnum++);
|
||||
|
@ -153,7 +147,6 @@ public class DataSaving
|
|||
HSSFCell passPercentCell = row.createCell(cellnum++);
|
||||
passPercentCell.setCellValue("Pass %");
|
||||
|
||||
//Save to file
|
||||
try (FileOutputStream outputStream = new FileOutputStream(outputFile))
|
||||
{ outputWorkbook.write(outputStream); }
|
||||
catch(Exception e) {ErrorLogging.logError(e);}
|
||||
|
@ -175,10 +168,8 @@ public class DataSaving
|
|||
int serialColumn = lastColumnOfData - 2;
|
||||
int percentColumn = lastColumnOfData - 1;
|
||||
|
||||
//Get the last row, add another row below it, and name the first cell "Totals:"
|
||||
int lastRowOfData = outputSheet.getLastRowNum();
|
||||
|
||||
//For each camera, create a unique total line
|
||||
int column = 1;
|
||||
for(int i = 0; i < cameraCount; i++)
|
||||
{
|
||||
|
@ -219,7 +210,6 @@ public class DataSaving
|
|||
column += 4;
|
||||
}
|
||||
|
||||
//Once all totals have been created, write to the file
|
||||
try (FileOutputStream outputStream = new FileOutputStream(outputFile))
|
||||
{ outputWorkbook.write(outputStream); }
|
||||
catch(Exception e) {ErrorLogging.logError(e);}
|
||||
|
@ -238,10 +228,8 @@ public class DataSaving
|
|||
boolean output = false;
|
||||
int cellnum = 0;
|
||||
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());
|
||||
//ErrorLogging.logError("DEBUG: image locations: " + imageLocations.toString());
|
||||
//List<Object> objectArray = new LinkedList<>();
|
||||
|
||||
cycle++;
|
||||
|
||||
|
@ -249,12 +237,10 @@ public class DataSaving
|
|||
indexCell.setCellValue(cycle);
|
||||
for(String cameraName : cameraNames)
|
||||
{
|
||||
//put serial number into sheet
|
||||
String serialNumber = ConfigFacade.getSerial(cameraName);
|
||||
HSSFCell serialCell = row.createCell(cellnum++);
|
||||
serialCell.setCellValue(serialNumber);
|
||||
|
||||
//Put the generated image into the spreadsheet
|
||||
File file = cameraToFile.get(cameraName);
|
||||
HSSFCell imageCell = row.createCell(cellnum++);
|
||||
try
|
||||
|
|
|
@ -61,10 +61,8 @@ public class ErrorLogging
|
|||
//Make sure the filename formatter is compatible with Windows and Linux
|
||||
fileDatetime = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss");
|
||||
|
||||
//Local formatter for logs
|
||||
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";
|
||||
File logDirectory = new File("logs");
|
||||
File outFile = new File(logFile);
|
||||
|
|
|
@ -20,7 +20,7 @@ import com.pi4j.io.pwm.PwmType;
|
|||
* Currently missing Run switch compatibility.
|
||||
*
|
||||
* @author Blizzard Finnegan
|
||||
* @version 3.0.0, 06 Mar. 2023
|
||||
* @version 3.0.1, 10 Mar. 2023
|
||||
*/
|
||||
public class MovementFacade
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ public class MovementFacade
|
|||
/**
|
||||
* Amount of buffer between the found absolute speed, and used speed.
|
||||
*/
|
||||
private static final int SPEED_BUFFER = 5000;
|
||||
private static final int SPEED_BUFFER = 7500;
|
||||
|
||||
/**
|
||||
* Minimum allowed speed of the fixture arm; also used for reset travels.
|
||||
|
@ -190,7 +190,7 @@ public class MovementFacade
|
|||
|
||||
static
|
||||
{
|
||||
//ErrorLogging.logError("DEBUG: Starting lock thread...");
|
||||
ErrorLogging.logError("DEBUG: Starting lock thread...");
|
||||
runSwitchThread = new Thread(() ->
|
||||
{
|
||||
boolean unlock = false;
|
||||
|
@ -198,7 +198,7 @@ public class MovementFacade
|
|||
{
|
||||
if(runSwitch.isOn())
|
||||
{
|
||||
ErrorLogging.logError("Run switch turned off!");
|
||||
ErrorLogging.logError("DEBUG: Run switch turned off!");
|
||||
while(!Cli.LOCK.tryLock())
|
||||
{}
|
||||
unlock = true;
|
||||
|
@ -214,24 +214,19 @@ public class MovementFacade
|
|||
}, "Run switch monitor.");
|
||||
runSwitchThread.start();
|
||||
|
||||
//Initialise Pi4J
|
||||
pi4j = Pi4J.newAutoContext();
|
||||
|
||||
//Initialise input pins
|
||||
upperLimit = inputBuilder("upperLimit", "Upper Limit Switch", UPPER_LIMIT_ADDR);
|
||||
lowerLimit = inputBuilder("lowerLimit", "Lower Limit Switch", LOWER_LIMIT_ADDR);
|
||||
runSwitch = inputBuilder("runSwitch" , "Run Switch" , RUN_SWITCH_ADDR);
|
||||
|
||||
//Initialise output pins
|
||||
motorEnable = outputBuilder("motorEnable" , "Motor Enable" , MOTOR_ENABLE_ADDR);
|
||||
motorDirection = outputBuilder("motorDirection", "Motor Direction", MOTOR_DIRECTION_ADDR);
|
||||
pistonActivate = outputBuilder("piston" , "Piston Activate", PISTON_ADDR);
|
||||
|
||||
//Initialise PWM object.
|
||||
pwm = pwmBuilder("pwm","PWM Pin",PWM_PIN_ADDR);
|
||||
pwm.on(DUTY_CYCLE, FREQUENCY);
|
||||
|
||||
//Find Distance and max speeds
|
||||
calibrate();
|
||||
}
|
||||
|
||||
|
@ -267,7 +262,6 @@ public class MovementFacade
|
|||
.frequency(FREQUENCY)
|
||||
.provider("pigpio-pwm")
|
||||
.initial(1)
|
||||
//On program close, turn off PWM.
|
||||
.shutdown(0);
|
||||
break;
|
||||
//Any pin not listed above must be software PWM controlled.
|
||||
|
@ -280,7 +274,6 @@ public class MovementFacade
|
|||
.frequency(FREQUENCY)
|
||||
.provider("pigpio-pwm")
|
||||
.initial(1)
|
||||
//On program close, turn off PWM.
|
||||
.shutdown(0);
|
||||
}
|
||||
return pi4j.create(configBuilder);
|
||||
|
@ -299,7 +292,6 @@ public class MovementFacade
|
|||
{
|
||||
DigitalInputConfigBuilder configBuilder = DigitalInput.newConfigBuilder(pi4j)
|
||||
.id(id)
|
||||
//.name(name)
|
||||
.address(address)
|
||||
.pull(PullResistance.PULL_DOWN)
|
||||
.debounce(3000L)
|
||||
|
@ -320,7 +312,6 @@ public class MovementFacade
|
|||
{
|
||||
DigitalOutputConfigBuilder configBuilder = DigitalOutput.newConfigBuilder(pi4j)
|
||||
.id(id)
|
||||
.name(name)
|
||||
.address(address)
|
||||
.shutdown(DigitalState.LOW)
|
||||
.initial(DigitalState.LOW)
|
||||
|
@ -382,8 +373,6 @@ public class MovementFacade
|
|||
resetArm();
|
||||
ErrorLogging.logError("Calibrating...");
|
||||
FREQUENCY = calib(MIN_FREQUENCY, MAX_FREQUENCY, 10000);
|
||||
//ErrorLogging.logError("Fine calibrating...");
|
||||
//FREQUENCY = calib(FREQUENCY,(FREQUENCY+10000),1000);
|
||||
ErrorLogging.logError("Calibration complete!");
|
||||
ErrorLogging.logError("DEBUG: Speed set to " + (FREQUENCY - SPEED_BUFFER));
|
||||
setFrequency(FREQUENCY - SPEED_BUFFER);
|
||||
|
@ -454,7 +443,6 @@ public class MovementFacade
|
|||
*/
|
||||
private static int calib(int start, int max, int iterate)
|
||||
{
|
||||
//start -= iterate;
|
||||
for(int i = start; i < max; i+=iterate)
|
||||
{
|
||||
if(!setFrequency(i))
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.io.File;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -37,11 +36,10 @@ import java.util.List;
|
|||
* Performs image capture, as well as image manipulation.
|
||||
*
|
||||
* @author Blizzard Finnegan
|
||||
* @version 2.1.0, 06 Mar. 2023
|
||||
* @version 3.0.0, 10 Mar. 2023
|
||||
*/
|
||||
public class OpenCVFacade
|
||||
{
|
||||
//Local variable instantiation
|
||||
/**
|
||||
* Storage of all cameras as Map.
|
||||
* To get available camera names, getKeys.
|
||||
|
@ -51,7 +49,7 @@ public class OpenCVFacade
|
|||
/**
|
||||
* 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.
|
||||
|
@ -129,7 +127,6 @@ public class OpenCVFacade
|
|||
*/
|
||||
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 + "...");
|
||||
File cameraLocation = new File(location);
|
||||
if (cameraLocation.exists())
|
||||
|
@ -171,7 +168,7 @@ public class OpenCVFacade
|
|||
* @return null if camera doesn't exist, or if capture fails;
|
||||
* otherwise, Frame of the taken image
|
||||
*/
|
||||
public static Mat takePicture(String cameraName)
|
||||
private static Mat takePicture(String cameraName)
|
||||
{
|
||||
Mat output = null;
|
||||
Frame temp = null;
|
||||
|
@ -199,12 +196,8 @@ public class OpenCVFacade
|
|||
*/
|
||||
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");
|
||||
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()));
|
||||
String canvasTitle = "Camera " + cameraName + " Preview";
|
||||
final CanvasFrame canvas = new CanvasFrame(canvasTitle);
|
||||
|
@ -212,20 +205,18 @@ public class OpenCVFacade
|
|||
return imageLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show current processed image to the GUI user.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public static String showImage(String cameraName, Object object)
|
||||
{
|
||||
//ErrorLogging.logError("DEBUG: Showing image from camera: " + cameraName);
|
||||
//ErrorLogging.logError("DEBUG: camera location: " + cameraMap.get(cameraName).toString());
|
||||
File imageLocation = completeProcess(cameraName,ConfigFacade.getImgSaveLocation() + "/config");
|
||||
return imageLocation.getPath();
|
||||
}
|
||||
///**
|
||||
// * Show current processed image to the GUI user.
|
||||
// *
|
||||
// * @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.
|
||||
// */
|
||||
//private static String showImage(String cameraName, Object object)
|
||||
//{
|
||||
// File imageLocation = completeProcess(cameraName,ConfigFacade.getImgSaveLocation() + "/config");
|
||||
// return imageLocation.getPath();
|
||||
//}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public static List<Mat> takeBurst(String cameraName, int frameCount)
|
||||
private static List<Mat> takeBurst(String cameraName, int frameCount)
|
||||
{
|
||||
List<Mat> output = null;
|
||||
//ErrorLogging.logError("DEBUG: takeBurst - Camera Name: " + cameraName);
|
||||
//ErrorLogging.logError("DEBUG: takeBurst - Possible camera names: " + getCameraNames().toString());
|
||||
if(getCameraNames().contains(cameraName))
|
||||
{
|
||||
output = new LinkedList<>();
|
||||
|
@ -272,7 +261,7 @@ public class OpenCVFacade
|
|||
* @param image Frame taken from the camera
|
||||
* @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 y = (int)ConfigFacade.getValue(cameraName,ConfigProperties.CROP_Y);
|
||||
|
@ -290,15 +279,9 @@ public class OpenCVFacade
|
|||
*
|
||||
* @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();
|
||||
//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;
|
||||
}
|
||||
|
||||
|
@ -311,7 +294,7 @@ public class OpenCVFacade
|
|||
*
|
||||
* @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 in = image;
|
||||
|
@ -328,7 +311,7 @@ public class OpenCVFacade
|
|||
*
|
||||
* @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;
|
||||
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.
|
||||
*/
|
||||
public static Mat compose(List<Mat> images, boolean threshold,
|
||||
private static Mat compose(List<Mat> images, boolean threshold,
|
||||
boolean crop, String cameraName)
|
||||
{
|
||||
ErrorLogging.logError("DEBUG: Attempting to compose " + images.size() + " images...");
|
||||
Mat output = null;
|
||||
int iterationCount = 1;
|
||||
for(Mat image : images)
|
||||
{ //crop and threshold, based on booleans
|
||||
Mat processedImage = image.clone();
|
||||
image.copyTo(processedImage);
|
||||
if(crop)
|
||||
{
|
||||
//ErrorLogging.logError("DEBUG: Cropping image " + iterationCount + "...");
|
||||
processedImage = crop(processedImage,cameraName);
|
||||
//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());
|
||||
{
|
||||
Mat processedImage = image.clone();
|
||||
image.copyTo(processedImage);
|
||||
if(crop) processedImage = crop(processedImage,cameraName);
|
||||
if(threshold) processedImage = thresholdImage(processedImage,cameraName);
|
||||
|
||||
if(iterationCount == 1) output = processedImage.clone();
|
||||
|
||||
if(iterationCount == 1)
|
||||
{
|
||||
output = processedImage.clone();
|
||||
}
|
||||
//ErrorLogging.logError("DEBUG: Thresholding image " + iterationCount + "...");
|
||||
bitwise_and((iterationCount == 1 ? processedImage : output),processedImage, output);
|
||||
|
||||
iterationCount++;
|
||||
}
|
||||
|
||||
if(output != null)
|
||||
ErrorLogging.logError("DEBUG: Compositing successful!");
|
||||
else
|
||||
ErrorLogging.logError("ERROR: Final output image is null!");
|
||||
if(output != null) ErrorLogging.logError("DEBUG: Compositing successful!");
|
||||
else ErrorLogging.logError("ERROR: Final output image is null!");
|
||||
return output;
|
||||
}
|
||||
|
||||
/**TODO: More robust file output checking;
|
||||
/**
|
||||
* Processes image from defined camera, using the config defaults.
|
||||
*
|
||||
*
|
||||
|
@ -429,18 +380,8 @@ public class OpenCVFacade
|
|||
ErrorLogging.logError("OPENCV ERROR!!! - Invalid camera name.");
|
||||
return output;
|
||||
}
|
||||
//ErrorLogging.logError("DEBUG: Camera to take picture from: " + cameraName);
|
||||
//ErrorLogging.logError("DEBUG: Composite frame count: " + 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);
|
||||
output = saveImage(finalImage, saveLocation,cameraName);
|
||||
return output;
|
||||
|
@ -458,21 +399,21 @@ public class OpenCVFacade
|
|||
public static File completeProcess(String cameraName, String saveLocation)
|
||||
{
|
||||
File output = null;
|
||||
|
||||
if(!getCameraNames().contains(cameraName))
|
||||
{
|
||||
ErrorLogging.logError("OPENCV ERROR!!! - Invalid camera name.");
|
||||
return output;
|
||||
}
|
||||
|
||||
int compositeFrames = (int)ConfigFacade.getValue(cameraName,ConfigProperties.COMPOSITE_FRAMES);
|
||||
//boolean threshold = false;
|
||||
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);
|
||||
//ErrorLogging.logError("DEBUG: Crop config value: " + crop);
|
||||
|
||||
boolean threshold = (ConfigFacade.getValue(cameraName,ConfigProperties.THRESHOLD) != 0.0);
|
||||
boolean crop = (ConfigFacade.getValue(cameraName,ConfigProperties.CROP) != 0.0);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -485,23 +426,5 @@ public class OpenCVFacade
|
|||
* @return null if any error occurs; otherwise File of output image
|
||||
*/
|
||||
public static File completeProcess(String cameraName)
|
||||
{
|
||||
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;
|
||||
}
|
||||
{ return completeProcess(cameraName,ConfigFacade.getImgSaveLocation()); }
|
||||
}
|
||||
|
|
|
@ -69,23 +69,16 @@ public class TesseractFacade
|
|||
*/
|
||||
public static double imageToDouble(File file)
|
||||
{
|
||||
//Set default output
|
||||
double output = Double.NEGATIVE_INFINITY;
|
||||
|
||||
//Import image, parse image
|
||||
PIX importedImage = pixRead(file.getAbsolutePath());
|
||||
api.SetImage(importedImage);
|
||||
String stringOutput = api.GetUTF8Text().getString();
|
||||
|
||||
//Determine whether the OCR output is actually a double
|
||||
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())
|
||||
{
|
||||
output = sc.nextDouble();
|
||||
|
@ -98,19 +91,14 @@ public class TesseractFacade
|
|||
output = output / 10;
|
||||
ErrorLogging.logError("OCR output saved, as value appears to be real. Value needs to be verified.");
|
||||
}
|
||||
else if(output >= 200)
|
||||
ErrorLogging.logError("OCR WARNING - OCR output is too high for DUT, potential misread.");
|
||||
else
|
||||
ErrorLogging.logError("OCR output successfully adjusted. Disregard warning.");
|
||||
else if(output >= 200) ErrorLogging.logError("OCR WARNING - OCR output is too high for DUT, potential misread.");
|
||||
else ErrorLogging.logError("OCR output successfully adjusted. Disregard warning.");
|
||||
}
|
||||
if(output <= -10)
|
||||
ErrorLogging.logError("OCR ERROR!!! - OCR output is too low for DUT, potential misread.");
|
||||
if(output <= -10) ErrorLogging.logError("OCR ERROR!!! - OCR output is too low for DUT, potential misread.");
|
||||
}
|
||||
else ErrorLogging.logError("OCR ERROR!!! - OCR output is not a Double.");
|
||||
}
|
||||
}
|
||||
|
||||
//Return output
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue