I'm developing a Face recognition from here using JavaCV 1.1, choose LBPH recognizer, when the program run shows the predicted image number from training folder.
for example: if folder contains the following images: steve1.png, steve2.png and judy3.png, judy4.png and the Person to classify is judy, prints
Predicted label: 4
That means the person is from judy4.png
I would like to show "judy" as predict label.
The method used for shows predicted label return an int, need to be a String
faceRecognizer.predict(personToClassify);
here's the code where the question is involved:
MatVector images = new MatVector(imageFiles.length);
Mat labels = new Mat(imageFiles.length, 1, CV_32SC1);
IntBuffer labelsBuf = labels.getIntBuffer();
int counter = 0;
for (File image : imageFiles) {
Mat img = imread(image.getAbsolutePath(), CV_LOAD_IMAGE_GRAYSCALE);
int label = Integer.parseInt(image.getName().split("\\-")[0]);
images.put(counter, img);
labelsBuf.put(counter, label);
counter++;
}
FaceRecognizer faceRecognizer = createFisherFaceRecognizer();
// FaceRecognizer faceRecognizer = createEigenFaceRecognizer();
// FaceRecognizer faceRecognizer = createLBPHFaceRecognizer()
faceRecognizer.train(images, labels);
int predictedLabel = faceRecognizer.predict(testImage);
System.out.println("Predicted label: " + predictedLabel);
Related
I am using itextpdf 7 (7.2.0) to create a pdf file. However even though the TOC part is rendered very well, in the content part the text overflows. Here is my code that generates the pdf:
public class Main {
public static void main(String[] args) throws IOException {
PdfWriter writer = new PdfWriter("fiftyfourthPdf.pdf");
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf, PageSize.A4,false);
//document.setMargins(30,10,36,10);
// Create a PdfFont
PdfFont font = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN,"Cp1254");
document
.setTextAlignment(TextAlignment.JUSTIFIED)
.setFont(font)
.setFontSize(11);
PdfOutline outline = null;
java.util.List<AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<String, Integer>>> toc = new ArrayList<>();
for(int i=0;i<5000;i++){
String line = "This is paragraph " + String.valueOf(i+1)+ " ";
line = line.concat(line).concat(line).concat(line).concat(line).concat(line);
Paragraph p = new Paragraph(line);
p.setKeepTogether(true);
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
//PROCESS FOR TOC
String name = "para " + String.valueOf(i+1);
outline = createOutline(outline,pdf,line ,name );
AbstractMap.SimpleEntry<String, Integer> titlePage = new AbstractMap.SimpleEntry(line, pdf.getNumberOfPages());
p
.setFont(font)
.setFontSize(12)
//.setKeepWithNext(true)
.setDestination(name)
// Add the current page number to the table of contents list
.setNextRenderer(new UpdatePageRenderer(p));
toc.add(new AbstractMap.SimpleEntry(name, titlePage));
}
int contentPageNumber = pdf.getNumberOfPages();
for (int i = 1; i <= contentPageNumber; i++) {
// Write aligned text to the specified by parameters point
document.showTextAligned(new Paragraph(String.format("Sayfa %s / %s", i, contentPageNumber)).setFontSize(10),
559, 26, i, TextAlignment.RIGHT, VerticalAlignment.MIDDLE, 0);
}
//BEGINNING OF TOC
document.add(new AreaBreak());
Paragraph p = new Paragraph("Table of Contents")
.setFont(font)
.setDestination("toc");
document.add(p);
java.util.List<TabStop> tabStops = new ArrayList<>();
tabStops.add(new TabStop(580, TabAlignment.RIGHT, new DottedLine()));
for (AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<String, Integer>> entry : toc) {
AbstractMap.SimpleEntry<String, Integer> text = entry.getValue();
p = new Paragraph()
.addTabStops(tabStops)
.add(text.getKey())
.add(new Tab())
.add(String.valueOf(text.getValue()))
.setAction(PdfAction.createGoTo(entry.getKey()));
document.add(p);
}
// Move the table of contents to the first page
int tocPageNumber = pdf.getNumberOfPages();
for (int i = 1; i <= tocPageNumber; i++) {
// Write aligned text to the specified by parameters point
document.showTextAligned(new Paragraph("\n footer text\n second line\nthird line").setFontColor(ColorConstants.RED).setFontSize(8),
300, 26, i, TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);
}
document.flush();
for(int z = 0; z< (tocPageNumber - contentPageNumber ); z++){
pdf.movePage(tocPageNumber,1);
pdf.getPage(1).setPageLabel(PageLabelNumberingStyle.UPPERCASE_LETTERS,
null, 1);
}
//pdf.movePage(tocPageNumber, 1);
// Add page labels
/*pdf.getPage(1).setPageLabel(PageLabelNumberingStyle.UPPERCASE_LETTERS,
null, 1);*/
pdf.getPage(tocPageNumber - contentPageNumber + 1).setPageLabel(PageLabelNumberingStyle.DECIMAL_ARABIC_NUMERALS,
null, 1);
document.close();
}
private static PdfOutline createOutline(PdfOutline outline, PdfDocument pdf, String title, String name) {
if (outline == null) {
outline = pdf.getOutlines(false);
outline = outline.addOutline(title);
outline.addDestination(PdfDestination.makeDestination(new PdfString(name)));
} else {
PdfOutline kid = outline.addOutline(title);
kid.addDestination(PdfDestination.makeDestination(new PdfString(name)));
}
return outline;
}
private static class UpdatePageRenderer extends ParagraphRenderer {
protected AbstractMap.SimpleEntry<String, Integer> entry;
public UpdatePageRenderer(Paragraph modelElement, AbstractMap.SimpleEntry<String, Integer> entry) {
super(modelElement);
this.entry = entry;
}
public UpdatePageRenderer(Paragraph modelElement) {
super(modelElement);
}
#Override
public LayoutResult layout(LayoutContext layoutContext) {
LayoutResult result = super.layout(layoutContext);
//entry.setValue(layoutContext.getArea().getPageNumber());
if (result.getStatus() != LayoutResult.FULL) {
if (null != result.getOverflowRenderer()) {
result.getOverflowRenderer().setProperty(
Property.LEADING,
result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
} else {
// if overflow renderer is null, that could mean that the whole renderer will overflow
setProperty(
Property.LEADING,
result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
}
}
return result;
}
#Override
// If not overriden, the default renderer will be used for the overflown part of the corresponding paragraph
public IRenderer getNextRenderer() {
return new UpdatePageRenderer((Paragraph) this.getModelElement());
}
}
}
Here are the screen shots of TOC part and content part :
TOC :
Content :
What am I missing? Thank you all for your help.
UPDATE
When I add the line below it renders with no overflow but the page margins of TOC and content part differ (the TOC margin is way more than the content margin). See the picture attached please :
document.setMargins(30,60,36,20);
Right Margin difference between TOC and content:
UPDATE 2 :
When I comment the line
document.setMargins(30,60,36,20);
and set the font size on line :
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
to 12 then it renders fine. What difference should possibly the font size cause for the page content and margins? Are not there standard page margins and page setups? Am I unknowingly (I am newbie to itextpdf) messing some standard implementations?
TL; DR: either remove setFontSize in
p
.setFont(font)
.setFontSize(12)
//.setKeepWithNext(true)
.setDestination(name)
or change setFontSize(10) -> setFontSize(12) in
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
Explanation: You are setting the Document to not immediately flush elements added to that document with the following line:
Document document = new Document(pdf, PageSize.A4,false);
Then you add an paragraph element with font size equal to 10 to the document with the following line:
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
What happens is that the element is being laid out (split in lines etc), but now drawn on the page. Then you do .setFontSize(12) and this new font size is applied for draw only, so iText calculated that X characters would fit into one line assuming the font size is 10 while in reality the font size is 12 and obviously fewer characters can fit into one line.
There is no sense in setting the font size two times to different values - just pick one value you want to see in the resultant document and set it once.
I want to plot a line which connects 2 points on a map.
The code I am using:
public class Quickstart {
public static void main(String[] args) throws Exception {
// display a data store file chooser dialog for shapefiles
File file = JFileDataStoreChooser.showOpenFile("shp", null);
if (file == null) {
return;
}
FileDataStore store = FileDataStoreFinder.getDataStore(file);
SimpleFeatureSource featureSource = store.getFeatureSource();
GeometryFactory gf = JTSFactoryFinder.getGeometryFactory();
// ask for current and destination positions
double latitude, longitude, latitudeDest, longitudeDest;
Scanner reader = new Scanner(System.in);
reader.useLocale(Locale.US);
System.out.println("Enter reference longitude and latitude:\n");
longitude = reader.nextDouble();
latitude = reader.nextDouble();
System.out.println("Enter destination longitude and latitude:\n");
longitudeDest = reader.nextDouble();
latitudeDest = reader.nextDouble();
reader.close();
final String EPSG4326 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\"," +
"\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\", " +
"0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
CoordinateReferenceSystem crs = CRS.parseWKT(EPSG4326);
Point start = gf.createPoint(new Coordinate(longitude, latitude));
Point end = gf.createPoint(new Coordinate(longitudeDest, latitudeDest));
GeodeticCalculator gc = new GeodeticCalculator(crs);
gc.setStartingPosition(JTS.toDirectPosition(start.getCoordinate(), crs));
gc.setDestinationPosition(JTS.toDirectPosition(end.getCoordinate(), crs));
// Calculate distance between points
double distance = gc.getOrthodromicDistance();
int totalmeters = (int) distance;
int km = totalmeters / 1000;
int meters = totalmeters - (km * 1000);
float remaining_cm = (float) (distance - totalmeters) * 10000;
remaining_cm = Math.round(remaining_cm);
float cm = remaining_cm / 100;
System.out.println("Distance = " + km + "km " + meters + "m " + cm + "cm");
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setName("TwoDistancesType");
builder.setCRS(DefaultGeographicCRS.WGS84);
builder.add("location", Point.class);
// build the type
final SimpleFeatureType TYPE = builder.buildFeatureType();
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
featureBuilder.add(start);
//featureBuilder.add(end);
SimpleFeature feature = featureBuilder.buildFeature(null);
DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", TYPE);
featureCollection.add(feature);
Style style = SLD.createSimpleStyle(TYPE, Color.red);
Layer layer = new FeatureLayer(featureCollection, style);
// Create a map content and add our shapefile to it
MapContent map = new MapContent();
map.setTitle("TEST");
map.addLayer(layer);
// Now display the map
JMapFrame.showMap(map);
}
}
I have 2 problems:
1) I can't add a second feature to featureBuilder.It doesn't allow it.It shows Can handle 1 attributes only, index is 1.
So, how can I plot a line then?
2) With the above code, I am receiving:
org.geotools.renderer.lite.StreamingRenderer fireErrorEvent SEVERE: The scale denominator must be positive
java.lang.IllegalArgumentException: The scale denominator must be positive
------- UPDATE ------------------------
After the solution that #Michael gave for the first question , now I no longer receive the error regarding the denominator, but I am receiving an empty map (white space).
----- UPDATE according to #iant suggestion ----------------
So, I tried this.Created a coordinates which holds the coordinates of the points (start and end) ,then created a linestring with those coordinates and added it to featurebuilder.
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setName("TwoDistancesType");
builder.setCRS(DefaultGeographicCRS.WGS84);
builder.add("line", LineString.class); //added a linestring class
final SimpleFeatureType TYPE = builder.buildFeatureType();
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
Coordinate[] coordinates = {start.getCoordinate(), end.getCoordinate()};
LineString line = gf.createLineString(coordinates);
featureBuilder.add(line);
and even though I am loading a map (countries.shp) it shows me an empty white space with a red line.
------ SOLUTION -------------
Ok, so the solution is (thanks to #iants comments):
Style style = SLD.createLineStyle(Color.red, 2.0f);
Layer layer = new FeatureLayer(featureCollection, style);
// Create style for the file
Style shpStyle = SLD.createSimpleStyle(TYPE, Color.blue);
Layer shpLayer = new FeatureLayer(featureSource, shpStyle);
// Create a map content and add our shapefile to it
MapContent map = new MapContent();
map.setTitle("TEST");
map.addLayer(layer);
map.addLayer(shpLayer);
and now you have a red line on a blue map!
You need to create a LineString from your points and then store that in your feature.
You should then get a correct scale but you might want to add some other data such as a coast line to the map first. The quick start tutorial can show you how to do that.
Disclaimer: I've never used geotools.
Looking at the source code of SimpleFeatureBuilder, add calls set which throws that error if:
if(index >= values.length)
throw new ArrayIndexOutOfBoundsException("Can handle "
+ values.length + " attributes only, index is " + index);
values is populated here:
values = new Object[featureType.getAttributeCount()];
so it's obvious that that problem is because your Type only has one property. Change it so it has two:
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setName("TwoDistancesType");
builder.setCRS(DefaultGeographicCRS.WGS84);
builder.add("start", Point.class);
builder.add("end", Point.class);
Essentially what I made is a flag quiz app that tests how many flags you guess correctly and gives you a percentage based score at the end.
The problem is that when I do the quiz I sometimes get an outOfBounds error and the app crashes instead of showing the score. It is pretty random because other times I can do the app 3-4 times no problems with the score displaying correctly at the end.
These are the 2 classes used when resetting the quiz at the end, The problem is String nextImage = quizCountriesList.remove(0); inside of loadNextFlag()
the exact error is:
at
java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.remove(ArrayList.java:403)
at
com.map524s1a.flagquizdk.MainActivityFragment.loadNextFlag(MainActivityFragment.java:180)
public void resetQuiz() {
// use AssetManager to get image file names for enabled regions
AssetManager assets = getActivity().getAssets();
fileNameList.clear(); // empty list of image file names
try {
// loop through each region
for (String region : regionsSet) {
// get a list of all flag image files in this region
String[] paths = assets.list(region);
for (String path : paths)
fileNameList.add(path.replace(".png", ""));
}
} catch (IOException ex) {
Log.e(TAG, "Error loading image file names", ex);
}
correctAnswers = 0; // reset the number of correct answers made
questions = 0; // reset the total number of questions
quizCountriesList.clear(); // clear prior list of quiz countries
int flagCounter = 1;
int numberOfFlags = fileNameList.size();
// add FLAGS_IN_QUIZ random file names to the quizCountriesList
while (flagCounter <= FLAGS_IN_QUIZ) {
int randomIndex = random.nextInt(numberOfFlags);
// get the random file name
String filename = fileNameList.get(randomIndex);
// if the region is enabled and it hasn't already been chosen
if (!quizCountriesList.contains(filename)) {
quizCountriesList.add(filename); // add the file to the list
++flagCounter;
}
}
loadNextFlag(); // start the quiz by loading the first flag
}
// after the user guesses a correct flag, load the next flag
private void loadNextFlag() {
// get file name of the next flag and remove it from the list
String nextImage = quizCountriesList.remove(0);
correctAnswer = nextImage; // update the correct answer
answerTextView.setText(""); // clear answerTextView
// display current question number
questionNumberTextView.setText(getString(R.string.question, (questions + 1), FLAGS_IN_QUIZ));
// extract the region from the next image's name
String region = nextImage.substring(0, nextImage.indexOf('-'));
// use AssetManager to load next image from assets folder
AssetManager assets = getActivity().getAssets();
// get an InputStream to the asset representing the next flag
// and try to use the InputStream
try (InputStream stream =
assets.open(region + "/" + nextImage + ".png")) {
// load the asset as a Drawable and display on the flagImageView
Drawable flag = Drawable.createFromStream(stream, nextImage);
flagImageView.setImageDrawable(flag);
animate(false); // animate the flag onto the screen
}
catch (IOException exception) {
Log.e(TAG, "Error loading " + nextImage, exception);
}
Collections.shuffle(fileNameList); // shuffle file names
// put the correct answer at the end of fileNameList
int correct = fileNameList.indexOf(correctAnswer);
fileNameList.add(fileNameList.remove(correct));
// add 2, 4, 6 or 8 guess Buttons based on the value of guessRows
for (int row = 0; row < guessRows; row++) {
// place Buttons in currentTableRow
for (int column = 0;
column < guessLinearLayouts[row].getChildCount();
column++) {
// get reference to Button to configure
Button newGuessButton =
(Button) guessLinearLayouts[row].getChildAt(column);
newGuessButton.setEnabled(true);
// get country name and set it as newGuessButton's text
String filename = fileNameList.get((row * 2) + column);
newGuessButton.setText(getCountryName(filename));
}
}
// randomly replace one Button with the correct answer
int row = random.nextInt(guessRows); // pick random row
int column = random.nextInt(2); // pick random column
LinearLayout randomRow = guessLinearLayouts[row]; // get the row
String countryName = getCountryName(correctAnswer);
((Button) randomRow.getChildAt(column)).setText(countryName);
}
I've created a platform game where each type of game object is assigned to specific rgb values so I can create levels by drawing them out in paint and loading the image. Right now I have the first two levels already loaded and I am able to get the path of the 3rd level through a textfield input and load a custom 3rd level. Each level needs a path to the png image of the level, and the number of coins needed to progress to the next level. I want to have every level load up from one text file where each line maybe has the level number, the image path, and the # of coins. I'm making it to be customizable so that the user can add or change levels simply by adding these parameters through 3 textfields in my customize menu. This way also my designer can help create levels and by reading from the text file I imagine there will be a lot less code in the long run when there are 20+ levels. Any ideas on how I can load from and append to this file? Here's what I'm working with right now:
public static BufferedImageLoader loader = new BufferedImageLoader();
public Handler(Camera cam){
this.cam = cam;
level1 = loader.loadImage("/level1.png");
level2 = loader.loadImage("/level2.png");
}
public void changeLevel(){
clearLevel();
cam.setX(0);
Player.coinCount = 0;
if(Game.LEVEL == 1){
Player.maxCoins = 4;
LoadImageLevel(level1);
}
if(Game.LEVEL == 2){
LoadImageLevel(level2);
Player.maxCoins = 11;
}
if(Game.LEVEL == 3){
System.out.println(Data.levelPath);
try{
level3 = loader.loadImage(Data.levelPath);
LoadImageLevel(level3);
} catch (Exception e) {
e.printStackTrace();
System.out.println("error loading custom level");
}
}
}
public Menu(Game game, Handler handler){
this.handler = handler;
pathField = new JTextField(10);
levelField = new JTextField(10);
coinField = new JTextField(10);
if(Game.gameState == STATE.Menu){
int selection = JOptionPane.showConfirmDialog(
null, getPanel(), "Input Form : "
, JOptionPane.OK_CANCEL_OPTION
, JOptionPane.PLAIN_MESSAGE);
if(selection == JOptionPane.OK_OPTION) {
Data.levelPath = pathField.getText();
Data.level = levelField.getText();
Data.coinAmount = Double.valueOf(coinField.getText());
System.out.println(Data.levelPath + Data.level + Data.coinAmount);
}
}
private JPanel getPanel(){
JPanel basePanel = new JPanel();
basePanel.setOpaque(true);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(3, 2, 5, 5));
centerPanel.setBorder(
BorderFactory.createEmptyBorder(5, 5, 5, 5));
centerPanel.setOpaque(true);
JLabel mLabel1 = new JLabel("Enter path: (e.g., /level1.png) ");
JLabel mLabel2 = new JLabel("Enter which level to load the image in: ");
JLabel mLabel3 = new JLabel("Enter the amount of coins you must collect");
centerPanel.add(mLabel1);
centerPanel.add(pathField);
centerPanel.add(mLabel2);
centerPanel.add(levelField);
centerPanel.add(mLabel3);
centerPanel.add(coinField);
basePanel.add(centerPanel);
return basePanel;
}
Any ideas or suggestions are appreciated!
It's actually just....
Given a value of the input.getText() as 1#path#20, It have level number, the image path, and the number of coins separated by # token.
public static String [] separateFields(String input, String separator){
String[] separatedValues = input.split("#");
return separatedValues;
}
Call the function, define the arguments.
// input is textfield.getText() , and the value of input is 1#path#20
String [] result= separateFields(input, "#");
Then you get
int level = Integer.parseInt(result[0]); // level
String aPath = result[1]; // path
int numCoins = Integer.parseInt(result[2]); // number of coins
I am trying to extract the bounding boxes of each word from the javacpp tesseract. This appears to be the bounding box call (my full code below):
boolean box = ri.BoundingBox(RIL_WORD, coord1, coord2, coord3, coord4)
RIL_WORD is the iterator level that can be adjusted for words, sentences, and paragraphs. The coordinates are IntPointers (included class with javacpp).
The api says this returns the bounding box coordinates but returns a boolean instead. SO at this point I know there is a bounding box but still cannot get the actual coordinates. Does anyone know how to get the bounding box rectangles out of java cpp tessaract? Thanks for the help. I have posted my working code for getting the individual words and the confidence level below because I had such a hard time finding examples.
public class TesseractOCR {
public void OCRText() {
BytePointer outText;
TessBaseAPI api = new TessBaseAPI();
// Initialize tesseract-ocr with English, without specifying tessdata path
if (api.Init(null, "eng") != 0) {
System.err.println("Could not initialize tesseract.");
System.exit(1);
}
// Open input image with leptonica library
org.bytedeco.javacpp.lept.PIX image = pixRead("testimage.png");
// Get OCR result
outText = api.GetUTF8Text();
System.out.println("OCR output:\n" + outText.getString());
final ResultIterator ri = api.GetIterator();
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
IntPointer coord1 = new IntPointer(x1);
IntPointer coord2 = new IntPointer(y1);
IntPointer coord3 = new IntPointer(x2);
IntPointer coord4 = new IntPointer(y2);
ri.Begin();
if (ri !=null) {
do {
BytePointer word = ri.GetUTF8Text(RIL_WORD);
float conf = ri.Confidence(RIL_WORD);
boolean box = ri.BoundingBox(RIL_WORD, coord1, coord2, coord3, coord4);
System.out.println(word.getString());
System.out.println(conf);
System.out.println(box);
} while (ri.Next(RIL_WORD));
}
api.End();
outText.deallocate();
pixDestroy(image);
}
}