Face Detection using a webcam interface in Java in Windows - java

I am new to OpenCV, and working on a face detection project. I wanted to create a webcam interface for face detection and I referred to the tutorial: here
I made following changes to the code( modification to the CascadeClassifier position and HaarCascade file path only):
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Size;
import org.opencv.core.Scalar;
import org.opencv.highgui.Highgui;
import org.opencv.highgui.VideoCapture;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import static com.googlecode.javacv.cpp.opencv_core.cvFlip;
public class detedctAndDisplay {
/** Global variables */
private static String face_cascade_name = "haarcascade_frontalface_alt.xml";
private static String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
private static CascadeClassifier face_cascade;
private static CascadeClassifier eyes_cascade;
private static String window_name = "Capture - Face detection";
public detedctAndDisplay(){
face_cascade = new CascadeClassifier("C:\\Users\\Admin\\Desktop\\face detection\\FaceDetection\\src\\haarcascade_frontalface_alt.xml");
eyes_cascade = new CascadeClassifier("C:\\Users\\Admin\\Desktop\\face detection\\FaceDetection\\src\\"+eyes_cascade_name);
}
public static void detectAndDisplay(Mat frame)
{
CascadeClassifier face_cascade= new CascadeClassifier("C:\\Users\\Admin\\Desktop\\face detection\\FaceDetection\\src\\haarcascade_frontalface_alt.xml");
Mat frame_gray = new Mat();
MatOfRect faces = new MatOfRect();
Rect[] facesArray = faces.toArray();
// Imgproc.cvtColor(frame, frame_gray, Imgproc.COLOR_BGRA2GRAY);
Imgproc.equalizeHist(frame_gray, frame_gray);
//-- Detect faces
face_cascade.detectMultiScale(frame_gray,faces );
for (int i = 0; i < facesArray.length; i++)
{
Point center = new Point(facesArray[i].x + facesArray[i].width * 0.5, facesArray[i].y + facesArray[i].height * 0.5);
Core.ellipse(frame, center, new Size(facesArray[i].width * 0.5, facesArray[i].height * 0.5), 0, 0, 360, new Scalar(255, 0, 255), 4, 8, 0);
Mat faceROI = frame_gray.submat(facesArray[i]);
MatOfRect eyes = new MatOfRect();
Rect[] eyesArray = eyes.toArray();
//-- In each face, detect eyes
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0,new Size(30, 30), new Size());
for (int j = 0; j < eyesArray.length; j++)
{
Point center1 = new Point(facesArray[i].x + eyesArray[i].x + eyesArray[i].width * 0.5, facesArray[i].y + eyesArray[i].y + eyesArray[i].height * 0.5);
int radius = (int) Math.round((eyesArray[i].width + eyesArray[i].height) * 0.25);
Core.circle(frame, center1, radius, new Scalar(255, 0, 0), 4, 8, 0);
}
}
//-- Show what you got
Highgui.imwrite(window_name, frame);
}
/**
* #param args
*/
public static void main(String[] args)
{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//face_cascade = new CascadeClassifier("C:\\Users\\Admin\\Desktop\\face detection\\FaceDetection\\src\\haarcascade_frontalface_alt.xml");
CascadeClassifier face_cascade1 = new CascadeClassifier("C:\\Users\\Admin\\Desktop\\face detection\\FaceDetection\\src\\haarcascade_frontalface_alt.xml");
//eyes_cascade = new CascadeClassifier("C:\\Users\\Admin\\Desktop\\face detection\\FaceDetection\\src\\"+eyes_cascade_name);
VideoCapture capture;
Mat frame = new Mat();
capture = new VideoCapture(0);
if(!capture.isOpened())
{
System.out.println("Did not connect to camera.");
}
else
{
capture.retrieve(frame);
detectAndDisplay(frame);
capture.release();
}
}
}
I am getting following error:
OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type
in unknown function, file ..\..\..\..\opencv\modules\core\src\array.cpp, line 2482
Exception in thread "main" CvException [org.opencv.core.CvException:
cv::Exception: ..\..\..\..\opencv\modules\core\src\array.cpp:2482: error: (-206) Unrecognized or
unsupported array type
]
at org.opencv.objdetect.CascadeClassifier.detectMultiScale_1(Native Method)
at org.opencv.objdetect.CascadeClassifier.detectMultiScale(CascadeClassifier.java:127)
at detedctAndDisplay.detectAndDisplay(detedctAndDisplay.java:55)
at detedctAndDisplay.main(detedctAndDisplay.java:125)
I am unable to resolve the error.
Also, please tell which jar to import so that cvtColor could be used?
Thanks!

OpenCV is complaining that the "array" (matrix, or image) type is not known because you never initialized frame_gray. You need to actually convert the image to grayscale. You actually have a line that does it but it's commented out:
// Imgproc.cvtColor(frame, frame_gray, Imgproc.COLOR_BGRA2GRAY);
Uncomment that line.

Related

YOLO...Program doesnt go through the loop to analyze each frame

Recently I am trying to implement an image object detection tool based on YOLO. To start with, I have used the codes here. Things sounds fine except the fact the program doesnt pass the following line of code (line 72) and will not go into the loop. :
if (cap.read(frame))
In other words, if a break point is placed at that line, the program wont go to next step.. Any idea how to fix this?
package yoloexample;
import org.opencv.core.*;
import org.opencv.dnn.*;
import org.opencv.utils.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Yoloexample {
private static List<String> getOutputNames(Net net) {
List<String> names = new ArrayList<>();
List<Integer> outLayers = net.getUnconnectedOutLayers().toList();
List<String> layersNames = net.getLayerNames();
outLayers.forEach((item) -> names.add(layersNames.get(item - 1)));//unfold and create R-CNN layers from the loaded YOLO model//
System.out.println(names);
return names;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
System.load("\\opencv\\opencv\\build\\java\\x64\\opencv_java420.dll"); // Load the openCV 4.0 dll //
String modelWeights = "g:\\yolov3.weights"; //Download and load only wights for YOLO , this is obtained from official YOLO site//
String modelConfiguration = "g:\\yolov3.cfg";//Download and load cfg file for YOLO , can be obtained from official site//
String filePath = "test.mp4"; //My video file to be analysed//
VideoCapture cap = new VideoCapture(filePath);// Load video using the videocapture method//
Mat frame = new Mat(); // define a matrix to extract and store pixel info from video//
//cap.read(frame);
JFrame jframe = new JFrame("Video"); // the lines below create a frame to display the resultant video with object detection and localization//
JLabel vidpanel = new JLabel();
jframe.setContentPane(vidpanel);
jframe.setSize(600, 600);
jframe.setVisible(true);// we instantiate the frame here//
Net net = Dnn.readNetFromDarknet(modelConfiguration, modelWeights); //OpenCV DNN supports models trained from various frameworks like Caffe and TensorFlow. It also supports various networks architectures based on YOLO//
//Thread.sleep(5000);
//Mat image = Imgcodecs.imread("D:\\yolo-object-detection\\yolo-object-detection\\images\\soccer.jpg");
Size sz = new Size(288, 288);
List<Mat> result = new ArrayList<>();
List<String> outBlobNames = getOutputNames(net);
while (true) {
if (cap.read(frame)) {
Mat blob = Dnn.blobFromImage(frame, 0.00392, sz, new Scalar(0), true, false); // We feed one frame of video into the network at a time, we have to convert the image to a blob. A blob is a pre-processed image that serves as the input.//
net.setInput(blob);
net.forward(result, outBlobNames); //Feed forward the model to get output //
// outBlobNames.forEach(System.out::println);
// result.forEach(System.out::println);
float confThreshold = 0.6f; //Insert thresholding beyond which the model will detect objects//
List<Integer> clsIds = new ArrayList<>();
List<Float> confs = new ArrayList<>();
List<Rect> rects = new ArrayList<>();
for (int i = 0; i < result.size(); ++i) {
// each row is a candidate detection, the 1st 4 numbers are
// [center_x, center_y, width, height], followed by (N-4) class probabilities
Mat level = result.get(i);
for (int j = 0; j < level.rows(); ++j) {
Mat row = level.row(j);
Mat scores = row.colRange(5, level.cols());
Core.MinMaxLocResult mm = Core.minMaxLoc(scores);
float confidence = (float) mm.maxVal;
Point classIdPoint = mm.maxLoc;
if (confidence > confThreshold) {
int centerX = (int) (row.get(0, 0)[0] * frame.cols()); //scaling for drawing the bounding boxes//
int centerY = (int) (row.get(0, 1)[0] * frame.rows());
int width = (int) (row.get(0, 2)[0] * frame.cols());
int height = (int) (row.get(0, 3)[0] * frame.rows());
int left = centerX - width / 2;
int top = centerY - height / 2;
clsIds.add((int) classIdPoint.x);
confs.add((float) confidence);
rects.add(new Rect(left, top, width, height));
}
}
}
float nmsThresh = 0.5f;
MatOfFloat confidences = new MatOfFloat(Converters.vector_float_to_Mat(confs));
Rect[] boxesArray = rects.toArray(new Rect[0]);
MatOfRect boxes = new MatOfRect(boxesArray);
MatOfInt indices = new MatOfInt();
Dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThresh, indices); //We draw the bounding boxes for objects here//
int[] ind = indices.toArray();
int j = 0;
for (int i = 0; i < ind.length; ++i) {
int idx = ind[i];
Rect box = boxesArray[idx];
Imgproc.rectangle(frame, box.tl(), box.br(), new Scalar(0, 0, 255), 2);
//i=j;
System.out.println(idx);
}
// Imgcodecs.imwrite("D://out.png", image);
//System.out.println("Image Loaded");
ImageIcon image = new ImageIcon(Mat2bufferedImage(frame)); //setting the results into a frame and initializing it //
vidpanel.setIcon(image);
vidpanel.repaint();
System.out.println(j);
System.out.println("Done");
}
}
}
private static BufferedImage Mat2bufferedImage(Mat image) { // The class described here takes in matrix and renders the video to the frame //
MatOfByte bytemat = new MatOfByte();
Imgcodecs.imencode(".jpg", image, bytemat);
byte[] bytes = bytemat.toArray();
InputStream in = new ByteArrayInputStream(bytes);
BufferedImage img = null;
try {
img = ImageIO.read(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return img;
}
}

Creating PDF push buttons with PDFBox 2.0.5 that shows/hides another button on the page. Only the last set created works properly

The goal of this code is to have a thumbnail image on the page, and when hovered over by the mouse it shows the image in full size. The code here works with the major caveat that only the final thumbnail-full image combo created will work unless in Adobe Acrobat Pro, I go to Tools > Interactive Objects > Add Button. then all of the buttons visible on the screen will work. If I pass the mouse over any thumbnail, then the large button associated with it is removed from the opened document. I have tried setNeedAppearances(true) and the actions will work for all combos, but the widget formatting is removed. Attached below is my test code. Any help would be greatly appreciated. Thanks.
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import java.io.IOException;
public class TestMain {
public static void main(String[] args) throws IOException {
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
float[] location = new float[]{100 , 600 , 60 , 80};
TestButton.makeButton(document , page , location , "1.jpg");
float[] location2 = new float[]{100 , 400 , 60 , 80};
TestButton.makeButton(document , page , location2 , "2.jpg");
document.save("mytest.pdf");
document.close();
}
}
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionHide;
import org.apache.pdfbox.pdmodel.interactive.action.PDAnnotationAdditionalActions;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceCharacteristicsDictionary;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDPushButton;
import java.io.IOException;
import java.util.ArrayList;
public class TestButton {
public static void makeButton(PDDocument document , PDPage page , float[] thumbLocation, String imageName) throws IOException {
PDImageXObject image = PDImageXObject.createFromFile("src//main/resources/" + imageName, document);
// thumbLocation array
float thumbX = thumbLocation[0];
float thumbY = thumbLocation[1];
float thumbWidth = thumbLocation[2];
float thumbHeight = thumbLocation[3];
float lowX = page.getMediaBox().getLowerLeftX();
float lowY = page.getMediaBox().getLowerLeftY();
float highY = page.getMediaBox().getUpperRightY();
float fullX = thumbX - image.getWidth() - 10;
if (fullX < lowX + 10){
fullX = thumbX + thumbWidth + 10;
}
float fullY = (thumbY + thumbHeight / 2) - (image.getHeight() / 2);
if (fullY < lowY + 10){
fullY = thumbY + thumbHeight + 10;
}
if (fullY + image.getHeight() > highY - 10){
fullY = thumbY - image.getHeight() - 10;
}
float fullWidth = image.getWidth();
float fullHeight = image.getHeight();
String thumbImage = imageName + "_Thumb";
String fullImage = imageName + "_Full";
PDColor colourBlack = new PDColor(new float[] { 0, 0, 0 }, PDDeviceRGB.INSTANCE);
// Set up thumbnail
COSDictionary thumbDict = new COSDictionary();
PDAcroForm thumbAcro = new PDAcroForm(document , thumbDict);
document.getDocumentCatalog().setAcroForm(thumbAcro);
thumbAcro.setFields(new ArrayList<>());
PDPushButton thumbButton = new PDPushButton(thumbAcro);
thumbButton.setPartialName(thumbImage);
// Thumbnail actions
thumbDict.setItem(COSName.T, new COSString(fullImage));
PDActionHide actionHide = new PDActionHide();
actionHide.setT(thumbDict);
PDActionHide actionShow = new PDActionHide();
actionShow.setT(thumbDict);
actionShow.setH(false);
PDAnnotationAdditionalActions additionalActions = new PDAnnotationAdditionalActions();
additionalActions.setE(actionShow);
additionalActions.setX(actionHide);
// Thumbnail widget
PDAnnotationWidget thumbWidget = thumbButton.getWidgets().get(0);
thumbWidget.setActions(additionalActions);
thumbWidget.setRectangle(new PDRectangle(thumbX, thumbY, thumbWidth, thumbHeight));
// Thumbnail appearance
PDAppearanceDictionary thumbAppearanceDict = new PDAppearanceDictionary();
PDAppearanceStream thumbAppearanceStream = new PDAppearanceStream(document);
thumbAppearanceStream.setResources(new PDResources());
PDAppearanceCharacteristicsDictionary thumbFieldAppearance
= new PDAppearanceCharacteristicsDictionary(new COSDictionary());
thumbFieldAppearance.setBorderColour(colourBlack);
thumbWidget.setAppearanceCharacteristics(thumbFieldAppearance);
try (PDPageContentStream thumbContent = new PDPageContentStream(document, thumbAppearanceStream))
{
PDRectangle thumbBox = new PDRectangle(
thumbWidget.getRectangle().getWidth(), thumbWidget.getRectangle().getHeight());
thumbAppearanceStream.setBBox(thumbBox);
thumbContent.setNonStrokingColor(0, 0, 0);
thumbContent.setLineWidth(0.5f);
thumbContent.addRect(thumbBox.getLowerLeftX() + 0.5f, thumbBox.getLowerLeftY() + 0.5f,
thumbBox.getWidth() - 1, thumbBox.getHeight() - 1);
thumbContent.stroke();
thumbContent.drawImage(image , thumbBox.getLowerLeftX() + 0.5f, thumbBox.getLowerLeftY() + 0.5f,
thumbBox.getWidth() - 1, thumbBox.getHeight() - 1);
}
thumbAppearanceDict.setNormalAppearance(thumbAppearanceStream);
thumbWidget.setAppearance(thumbAppearanceDict);
thumbWidget.setHidden(false);
thumbWidget.setPrinted(true);
page.getAnnotations().add(thumbWidget);
thumbAcro.getFields().add(thumbButton);
// Set up full
COSDictionary fullDict = new COSDictionary();
PDAcroForm fullAcro = new PDAcroForm(document , fullDict);
document.getDocumentCatalog().setAcroForm(fullAcro);
fullAcro.setFields(new ArrayList<>());
PDPushButton fullButton = new PDPushButton(fullAcro);
fullButton.setPartialName(fullImage);
// Full widget
PDAnnotationWidget fullWidget = fullButton.getWidgets().get(0);
fullWidget.setRectangle(new PDRectangle(fullX - 1 , fullY - 1, fullWidth + 2 , fullHeight + 2));
// Full appearance
PDAppearanceDictionary fullAppearanceDict = new PDAppearanceDictionary();
PDAppearanceStream fullAppearanceStream = new PDAppearanceStream(document);
fullAppearanceStream.setResources(new PDResources());
PDAppearanceCharacteristicsDictionary fullFieldAppearance
= new PDAppearanceCharacteristicsDictionary(new COSDictionary());
fullFieldAppearance.setBorderColour(colourBlack);
fullWidget.setAppearanceCharacteristics(fullFieldAppearance);
try (PDPageContentStream fullContent = new PDPageContentStream(document, fullAppearanceStream))
{
PDRectangle fullBox = new PDRectangle(
fullWidget.getRectangle().getWidth(), fullWidget.getRectangle().getHeight());
fullAppearanceStream.setBBox(fullBox);
fullContent.setNonStrokingColor(0, 0, 0);
fullContent.setLineWidth(1);
fullContent.addRect(fullBox.getLowerLeftX() + 1, fullBox.getLowerLeftY() + 1,
fullBox.getWidth() - 2, fullBox.getHeight() - 2);
fullContent.stroke();
fullContent.drawImage(image, fullBox.getLowerLeftX() + 1, fullBox.getLowerLeftY() + 1,
fullBox.getWidth() - 2, fullBox.getHeight() - 2);
}
fullAppearanceDict.setNormalAppearance(fullAppearanceStream);
fullWidget.setAppearance(fullAppearanceDict);
fullWidget.setHidden(true);
fullWidget.setPrinted(false);
page.getAnnotations().add(fullWidget);
fullAcro.getFields().add(fullButton);
}
}
Thanks mkl, you sent me in the right Direction. I ended up making the TestButton class non-static and moved the Acroform definition to the main class. I am making the AcroForm without the Dictionary as that is set in the TestButton class. Here is the code:
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import java.io.IOException;
import java.util.ArrayList;
public class TestMain {
public static void main(String[] args) throws IOException {
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
PDAcroForm buttonAcro = new PDAcroForm(document);
document.getDocumentCatalog().setAcroForm(buttonAcro);
buttonAcro.setFields(new ArrayList<>());
TestButton button = new TestButton();
float[] location = new float[]{100 , 600 , 60 , 80};
button.makeButton(document , page , location , "1.jpg" , buttonAcro);
float[] location2 = new float[]{100 , 400 , 60 , 80};
button.makeButton(document , page , location2 , "2.jpg", buttonAcro);
document.save("mytest.pdf");
document.close();
}
}
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionHide;
import org.apache.pdfbox.pdmodel.interactive.action.PDAnnotationAdditionalActions;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceCharacteristicsDictionary;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDPushButton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TestButton {
public void makeButton(PDDocument document, PDPage page, float[] thumbLocation, String imageName,
PDAcroForm buttonAcro) throws IOException {
PDImageXObject image = PDImageXObject.createFromFile("src//main/resources/" + imageName, document);
float thumbX = thumbLocation[0];
float thumbY = thumbLocation[1];
float thumbWidth = thumbLocation[2];
float thumbHeight = thumbLocation[3];
float lowX = page.getMediaBox().getLowerLeftX();
float lowY = page.getMediaBox().getLowerLeftY();
float highY = page.getMediaBox().getUpperRightY();
float fullX = thumbX - image.getWidth() - 10;
if (fullX < lowX + 10){
fullX = thumbX + thumbWidth + 10;
}
float fullY = (thumbY + thumbHeight / 2) - (image.getHeight() / 2);
if (fullY < lowY + 10){
fullY = thumbY + thumbHeight + 10;
}
if (fullY + image.getHeight() > highY - 10){
fullY = thumbY - image.getHeight() - 10;
}
float fullWidth = image.getWidth();
float fullHeight = image.getHeight();
String thumbImage = imageName + "_Thumb";
String fullImage = imageName + "_Full";
PDColor colourBlack = new PDColor(new float[] { 0, 0, 0 }, PDDeviceRGB.INSTANCE);
// Set up thumbnail
COSDictionary thumbDict = new COSDictionary();
PDPushButton thumbButton = new PDPushButton(buttonAcro);
thumbButton.setPartialName(thumbImage);
// Thumbnail actions
thumbDict.setItem(COSName.T, new COSString(fullImage));
PDActionHide actionHide = new PDActionHide();
actionHide.setT(thumbDict);
PDActionHide actionShow = new PDActionHide();
actionShow.setT(thumbDict);
actionShow.setH(false);
PDAnnotationAdditionalActions additionalActions = new PDAnnotationAdditionalActions();
additionalActions.setE(actionShow);
additionalActions.setX(actionHide);
// Thumbnail widget
PDAnnotationWidget thumbWidget = thumbButton.getWidgets().get(0);
thumbWidget.setActions(additionalActions);
thumbWidget.setRectangle(new PDRectangle(thumbX, thumbY, thumbWidth, thumbHeight));
// Thumbnail appearance
PDAppearanceDictionary thumbAppearanceDict = new PDAppearanceDictionary();
PDAppearanceStream thumbAppearanceStream = new PDAppearanceStream(document);
thumbAppearanceStream.setResources(new PDResources());
PDAppearanceCharacteristicsDictionary thumbFieldAppearance
= new PDAppearanceCharacteristicsDictionary(new COSDictionary());
thumbFieldAppearance.setBorderColour(colourBlack);
thumbWidget.setAppearanceCharacteristics(thumbFieldAppearance);
try (PDPageContentStream thumbContent = new PDPageContentStream(document, thumbAppearanceStream))
{
PDRectangle thumbBox = new PDRectangle(
thumbWidget.getRectangle().getWidth(), thumbWidget.getRectangle().getHeight());
thumbAppearanceStream.setBBox(thumbBox);
thumbContent.setNonStrokingColor(0, 0, 0);
thumbContent.setLineWidth(0.5f);
thumbContent.addRect(thumbBox.getLowerLeftX() + 0.5f, thumbBox.getLowerLeftY() + 0.5f,
thumbBox.getWidth() - 1, thumbBox.getHeight() - 1);
thumbContent.stroke();
thumbContent.drawImage(image , thumbBox.getLowerLeftX() + 0.5f, thumbBox.getLowerLeftY() + 0.5f,
thumbBox.getWidth() - 1, thumbBox.getHeight() - 1);
}
thumbAppearanceDict.setNormalAppearance(thumbAppearanceStream);
thumbWidget.setAppearance(thumbAppearanceDict);
thumbWidget.setHidden(false);
thumbWidget.setPrinted(true);
page.getAnnotations().add(thumbWidget);
buttonAcro.getFields().add(thumbButton);
// Set up full
PDPushButton fullButton = new PDPushButton(buttonAcro);
fullButton.setPartialName(fullImage);
// Full widget
PDAnnotationWidget fullWidget = fullButton.getWidgets().get(0);
fullWidget.setRectangle(new PDRectangle(fullX - 1 , fullY - 1, fullWidth + 2 , fullHeight + 2));
// Full appearance
PDAppearanceDictionary fullAppearanceDict = new PDAppearanceDictionary();
PDAppearanceStream fullAppearanceStream = new PDAppearanceStream(document);
fullAppearanceStream.setResources(new PDResources());
PDAppearanceCharacteristicsDictionary fullFieldAppearance
= new PDAppearanceCharacteristicsDictionary(new COSDictionary());
fullFieldAppearance.setBorderColour(colourBlack);
fullWidget.setAppearanceCharacteristics(fullFieldAppearance);
try (PDPageContentStream fullContent = new PDPageContentStream(document, fullAppearanceStream))
{
PDRectangle fullBox = new PDRectangle(
fullWidget.getRectangle().getWidth(), fullWidget.getRectangle().getHeight());
fullAppearanceStream.setBBox(fullBox);
fullContent.setNonStrokingColor(0, 0, 0);
fullContent.setLineWidth(1);
fullContent.addRect(fullBox.getLowerLeftX() + 1, fullBox.getLowerLeftY() + 1,
fullBox.getWidth() - 2, fullBox.getHeight() - 2);
fullContent.stroke();
fullContent.drawImage(image, fullBox.getLowerLeftX() + 1, fullBox.getLowerLeftY() + 1,
fullBox.getWidth() - 2, fullBox.getHeight() - 2);
}
fullAppearanceDict.setNormalAppearance(fullAppearanceStream);
fullWidget.setAppearance(fullAppearanceDict);
fullWidget.setHidden(true);
fullWidget.setPrinted(false);
page.getAnnotations().add(fullWidget);
buttonAcro.getFields().add(fullButton);
}
}

How to adjust the threshold for template matching in openCV (java)?

I am running template matching using openCV 3.4.7 Android SDK (java).
The code work almost perfectly; when the template is match, it draws a rectangle on the matching area. The problem is that even when there is no match, it draws a random rectangle. I think that happens because the threshold is not set correctly. If so, can someone please help me out?
Here's the code:
public static void run(String inFile, String templateFile, String outFile,
int match_method) {
Mat img = Imgcodecs.imread(inFile);
Mat templ = Imgcodecs.imread(templateFile);
// / Create the result matrix
int result_cols = img.cols() - templ.cols() + 1;
int result_rows = img.rows() - templ.rows() + 1;
Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
// / Do the Matching and Normalize
Imgproc.matchTemplate(img, templ, result, match_method);
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
// / Localizing the best match with minMaxLoc
Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
Point matchLoc;
if (match_method == Imgproc.TM_SQDIFF
|| match_method == Imgproc.TM_SQDIFF_NORMED) {
matchLoc = mmr.minLoc;
} else {
matchLoc = mmr.maxLoc;
}
// / Show me what you got
Imgproc.rectangle(img, matchLoc, new Point(matchLoc.x + templ.cols(),
matchLoc.y + templ.rows()), new Scalar(0, 0, 128));
// Save the visualized detection.
System.out.println("Writing " + outFile);
Imgcodecs.imwrite(outFile, img);
}
You can use Imgproc.TM_CCOEFF_NORMED or Imgproc.TM_CCORR_NORMED and mmr.maxVal >= 0.8. It should take care of most of your false positives.
Sample Code:
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.io.File;
import java.nio.file.Files;
public class templateMatchingTester {
private static String str = null;
static {
if (str == null) {
str = "initialised";
nu.pattern.OpenCV.loadShared();
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
}
private static Mat createMatrixFromImage(String imagePath) {
Mat imageMatrix = Imgcodecs.imread(imagePath);
Mat greyImage = new Mat();
Imgproc.cvtColor(imageMatrix, greyImage, Imgproc.COLOR_BGR2GRAY);
return greyImage;
}
private static boolean matchTemplate(String pathToInputImage,String pathToTemplate){
Mat inputImage = createMatrixFromImage(pathToInputImage);
Mat templateImage = createMatrixFromImage(pathToTemplate);
// Create the result matrix
int result_cols = inputImage.cols() - templateImage.cols() + 1;
int result_rows = inputImage.rows() - templateImage.rows() + 1;
Mat result = new Mat(result_rows, result_cols, CvType.CV_8UC1);
int match_method;
match_method = Imgproc.TM_CCOEFF_NORMED;//Imgproc.TM_CCORR_NORMED;
Imgproc.matchTemplate(inputImage, templateImage, result, match_method);
Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
double minMatchQuality = 0.85;
System.out.println(mmr.maxVal);
if (mmr.maxVal >= minMatchQuality){
return true;
} else
return false;
}
public static void main(String args[]) {
String template = "path/to/your/templateImage";
final File folder = new File("path/to/your/testImagesFolder/");
int matchCount = 0;
for (final File fileEntry : folder.listFiles()){
if (matchTemplate(fileEntry.getPath(),template)){
matchCount+=1;
}else
System.out.println(fileEntry.getPath());
}
System.out.println(matchCount);
}
}
Use a normed match method to ensure your match value is [0..1].
Replace this line
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
with a thresholding operation. Otherwise a best match of 0.9 would become 1 by the second normalization and you would lose the actual match "quality" information.
Normalizing the result of the template matching will always result in your best match being 1 making it impossible to discard a bad match.
i wrote an app that would take a screenshot of the game overwatch and attempt to tell who is on each team. using template matching and open cv. project need to iterate over the result image and check values.
OpenCVUtils.getPointsFromMatAboveThreshold(result,
0.90f)
public static void scaleAndCheckAll(String guid){
Mat source = imread(IMG_PROC_PATH + guid); //load the source image
Mat scaledSrc = new Mat(defaultScreenshotSize, source.type());
resize(source, scaledSrc, defaultScreenshotSize);
Mat sourceGrey = new Mat(scaledSrc.size(), CV_8UC1);
cvtColor(scaledSrc, sourceGrey, COLOR_BGR2GRAY);
for (String hero : getCharacters()) {
Mat template = OpenCVUtils.matFromJar(TEMPLATES_FOLDER + hero + ".png", 0); //load a template
Size size = new Size(sourceGrey.cols()-template.cols()+1, sourceGrey.rows()-template.rows()+1);
Mat result = new Mat(size, CV_32FC1);
matchTemplate(sourceGrey, template, result, TM_CCORR_NORMED);// get results
Scalar color = OpenCVUtils.randColor();
List<Point> points = OpenCVUtils.getPointsFromMatAboveThreshold(result,
0.90f);
for (Point point : points) {
//rectangle(scaledSrc, new Rect(point.x(),point.y(),template.cols(),template.rows()), color, -2, 0, 0);
putText(scaledSrc, hero, point, FONT_HERSHEY_PLAIN, 2, color);
}
}
String withExt = IMG_PROC_PATH + guid +".png";
imwrite(withExt, scaledSrc);
File noExt = new File(IMG_PROC_PATH + guid);
File ext = new File(withExt);
noExt.delete();
ext.renameTo(noExt);
}
the other method.
public static List<Point> getPointsFromMatAboveThreshold(Mat m, float t){
List<Point> matches = new ArrayList<Point>();
FloatIndexer indexer = m.createIndexer();
for (int y = 0; y < m.rows(); y++) {
for (int x = 0; x < m.cols(); x++) {
if (indexer.get(y,x)>t) {
System.out.println("(" + x + "," + y +") = "+ indexer.get(y,x));
matches.add(new Point(x, y));
}
}
}
return matches;
}
you can just get the first from the list or see how close they are if you expect multiple matches.

Having three columns layout in PDF using itext7

I am new to itext7.
I saw an example about columndocumentrenderer. code below.
package com.itextpdf.highlevel.chapter02;
import com.itextpdf.io.font.FontConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.ColumnDocumentRenderer;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.hyphenation.HyphenationConfig;
import com.itextpdf.layout.property.AreaBreakType;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.test.annotations.WrapToTest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
/**
*
* #author RNDPC-03
*/#WrapToTest
public class C02E08_JekyllHydeV4 {
public static final String SRC = "src/main/resources/txt/jekyll_hyde.txt";
public static final String DEST = "results/chapter02/jekyll_hyde_v4.pdf";
public static void main(String args[]) throws IOException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new C02E08_JekyllHydeV4().createPdf(DEST);
}
public void createPdf(String dest) throws IOException {
//Initialize PDF document
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
// Initialize document
Document document = new Document(pdf);
//Set column parameters
float offSet = 36;
float gutter = 23;
float columnWidth = (PageSize.A4.getWidth() - offSet * 2) / 2 - gutter;
float columnHeight = PageSize.A4.getHeight() - offSet * 2;
//Define column areas
Rectangle[] columns = {
new Rectangle(offSet, offSet, columnWidth, columnHeight),
new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight)};
document.setRenderer(new ColumnDocumentRenderer(document, columns));
PdfFont font = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
PdfFont bold = PdfFontFactory.createFont(FontConstants.HELVETICA_BOLD);
document.setTextAlignment(TextAlignment.JUSTIFIED)
.setFont(font)
.setHyphenation(new HyphenationConfig("en", "uk", 3, 3));
BufferedReader br = new BufferedReader(new FileReader(SRC));
String line;
Paragraph p;
boolean title = true;
AreaBreak nextArea = new AreaBreak(AreaBreakType.NEXT_AREA);
while ((line = br.readLine()) != null) {
p = new Paragraph(line);
if (title) {
p.setFont(bold).setFontSize(12);
title = false;
}
else {
p.setFirstLineIndent(36);
}
if (line.isEmpty()) {
document.add(nextArea);
title = true;
}
document.add(p);
}
//Close document
document.close();
}
}
now this will have a result of this . picture below
now I want to make it into a three(3) column. how to do this? please anyone? or just guide me. thank you!
Here is where you define two columns:
float offSet = 36;
float gutter = 23;
float columnWidth = (PageSize.A4.getWidth() - offSet * 2) / 2 - gutter;
float columnHeight = PageSize.A4.getHeight() - offSet * 2;
//Define column areas
Rectangle[] columns = {
new Rectangle(offSet, offSet, columnWidth, columnHeight),
new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight)};
Changing this to three columns is a no-brainer.
Just replace all of the above by something like this:
Rectangle[] columns = {
new Rectangle(20, 20, 180, 802),
new Rectangle(207, 15, 180, 802),
new Rectangle(394, 15, 180, 802) };
Now that columns has three Rectangle elements, three columns will be drawn. Feel free to adapt the values of x, y, width and height in the Rectangle constructor if the three columns don't have the desired size.

Image perspective correction

I need to rotate my BufferedImage on 3 axis (x, y and z), by the angles given in 3 integers. Is there any native methods in java? If not, how would I achieve that?
Update #1: I've done some of it with OpenCV... Will update when finished!
Update #2: Since this was just a part of my project, I realized that solving just a part of the problem wouldn't be good, so I used OpenCV getPerspectiveTransform() and then warpPerspective() methods from Imgproc class to transform image. I have basically just ported this code to java and it works fine :)
Also I have changed the thread name due the changes to make it fit the actual question/solution.
Code (I used OpenCV 3.1, since it's the latest version):
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgcodecs.Imgcodecs;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
BufferedImage transformed = null;
//These locations are just the corners of the 4 reference points. I am writing the auto recognition part right now :)
Point p4 = new Point(260, 215);
Point p1 = new Point(412, 221);
Point p2 = new Point(464, 444);
Point p3 = new Point(312, 435);
public Main() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
File f = new File("FILEPATH ");
MatOfPoint2f corners = new MatOfPoint2f();
Mat src = Imgcodecs.imread(f.getAbsolutePath());
corners.push_back(new MatOfPoint2f(p1));
corners.push_back(new MatOfPoint2f(p2));
corners.push_back(new MatOfPoint2f(p3));
corners.push_back(new MatOfPoint2f(p4));
Point center = new Point(0, 0);
for (int i = 0; i < corners.toArray().length; i++) {
center.x += corners.toArray()[i].x;
center.y += corners.toArray()[i].y;
}
center.x /= corners.toArray().length;
center.y /= corners.toArray().length;
sortCorners(corners, center);
Mat quad = Mat.zeros(1000, 1900, CvType.CV_8U);
MatOfPoint2f quad_pts = new MatOfPoint2f();
quad_pts.push_back(new MatOfPoint2f(new Point(0, 0)));
quad_pts.push_back(new MatOfPoint2f(new Point(quad.width(), 0)));
quad_pts.push_back(new MatOfPoint2f(new Point(quad.width(), quad.height())));
quad_pts.push_back(new MatOfPoint2f(new Point(0, quad.height())));
Mat transmtx = Imgproc.getPerspectiveTransform(corners, quad_pts);
Imgproc.warpPerspective(src, quad, transmtx, quad.size());
transformed = matToBufferedImage(quad);
setSize(500, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g) {
g.clearRect(0, 0, this.getWidth(), this.getHeight());
g.drawImage(transformed, 0, 22, null);
}
public MatOfPoint2f sortCorners(MatOfPoint2f corners, Point center) {
MatOfPoint2f top = new MatOfPoint2f();
MatOfPoint2f bot = new MatOfPoint2f();
for (int i = 0; i < corners.toArray().length; i++) {
if (corners.toArray()[i].y < center.y){
top.push_back(new MatOfPoint2f(corners.toArray()[i]));
}
else
bot.push_back(new MatOfPoint2f(corners.toArray()[i]));
}
Point tl = p4;
Point tr = p1;
Point bl = p2;
Point br = p3;
tl = top.toArray()[0].x > top.toArray()[1].x ? top.toArray()[1] : top.toArray()[0];
tr = top.toArray()[0].x > top.toArray()[1].x ? top.toArray()[0] : top.toArray()[1];
bl = bot.toArray()[0].x > bot.toArray()[1].x ? bot.toArray()[1] : bot.toArray()[0];
br = bot.toArray()[0].x > bot.toArray()[1].x ? bot.toArray()[0] : bot.toArray()[1];
corners.release();
corners.push_back(new MatOfPoint2f(tl));
corners.push_back(new MatOfPoint2f(tr));
corners.push_back(new MatOfPoint2f(br));
corners.push_back(new MatOfPoint2f(bl));
System.out.println(corners.toArray()[0] + ", " + corners.toArray()[1] + ", " + corners.toArray()[2] + ", " + corners.toArray()[3] + ", ");
return corners;
}
public BufferedImage matToBufferedImage(Mat image) {
Mat image_tmp = image;
MatOfByte matOfByte = new MatOfByte();
Imgcodecs.imencode(".jpg", image_tmp, matOfByte);
byte[] byteArray = matOfByte.toArray();
BufferedImage bufImage = null;
try {
InputStream in = new ByteArrayInputStream(byteArray);
bufImage = ImageIO.read(in);
} catch (Exception e) {
e.printStackTrace();
}
return bufImage;
}
}
I think that the TransformJ package does what you want, but I don't think it contains native code.

Categories