Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,49 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<opencv.version>3.2.0-1.3</opencv.version>
</properties>

<dependencies>

<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>0.9</version>
<version>1.3</version>
</dependency>

<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>2.4.9-0.9</version>
<version>${opencv.version}</version>
</dependency>

<!-- <dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>${opencv.version}</version>
<classifier>windows-x86_64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>${opencv.version}</version>
<classifier>linux-x86_64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>${opencv.version}</version>
<classifier>macosx-x86_64</classifier>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>0.9</version>
</dependency> -->
<version>1.3</version>
</dependency>

<dependency>
<groupId>junit</groupId>
Expand All @@ -70,7 +92,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
<version>21.0</version>
</dependency>

<dependency>
Expand All @@ -87,8 +109,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
Expand Down
103 changes: 103 additions & 0 deletions src/main/java/org/sikuli/core/cv/ImageConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.sikuli.core.cv;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;

public final class ImageConverter {

public static void saveImage(IplImage image, String fileBaseName) {
Java2DFrameConverter jConv = new Java2DFrameConverter();
OpenCVFrameConverter.ToIplImage openCVConv = new OpenCVFrameConverter.ToIplImage();
try {
File f = new File("./target/" + fileBaseName + System.currentTimeMillis() + ".png");
System.out.println("Saving image at " + f.getAbsolutePath());
BufferedImage result = jConv.convert(openCVConv.convert(image.clone()));
//System.out.println("Image: " + result +", " + result.getWidth() + "x" + result.getHeight());
if (!ImageIO.write(result, "png", f)) {
System.err.println("Could not write image.");
}
} catch (IOException e) {
e.printStackTrace();
}
}

public static void saveImage(BufferedImage image, String fileBaseName) {
try {
ImageIO.write(image, "png", new File("./target/" + fileBaseName + System.currentTimeMillis() + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
}

public static IplImage convert(BufferedImage image) {
if (image == null) {
return null;
}
Java2DFrameConverter java2dConverter = new Java2DFrameConverter();
OpenCVFrameConverter.ToIplImage frameToImageConverter = new OpenCVFrameConverter.ToIplImage();
return frameToImageConverter.convert(java2dConverter.convert(image)).clone();
}

public static BufferedImage convert(IplImage image) {
OpenCVFrameConverter.ToIplImage frameToImageConverter = new OpenCVFrameConverter.ToIplImage();
Frame f = frameToImageConverter.convert(image);
Java2DFrameConverter java2dConverter = new Java2DFrameConverter();
return java2dConverter.convert(f);
}

public static Frame getFrame(BufferedImage image) {
Java2DFrameConverter java2dConverter = new Java2DFrameConverter();
Frame f = java2dConverter.convert(image);
return f;
}

public static Frame getFrame(IplImage image) {
OpenCVFrameConverter.ToIplImage frameToImageConverter = new OpenCVFrameConverter.ToIplImage();
Frame f = frameToImageConverter.convert(image);
return f;
}

public static Frame getFrame(Mat image) {
OpenCVFrameConverter.ToIplImage frameToImageConverter = new OpenCVFrameConverter.ToIplImage();
Frame f = frameToImageConverter.convert(image);
return f;
}

public static Mat convertToMat(BufferedImage image) {
OpenCVFrameConverter.ToMat frame2matConv = new OpenCVFrameConverter.ToMat();
Mat mat = frame2matConv.convert(getFrame(image));
return mat;
}

public static BufferedImage convertFromMat(Mat image) {
OpenCVFrameConverter.ToMat frame2matConv = new OpenCVFrameConverter.ToMat();
Frame f = frame2matConv.convert(image);
Java2DFrameConverter java2dConverter = new Java2DFrameConverter();
return java2dConverter.convert(f);
}

public static Mat convertToMat(IplImage image) {
OpenCVFrameConverter.ToIplImage img2frameConv = new OpenCVFrameConverter.ToIplImage();
OpenCVFrameConverter.ToMat frame2matConv = new OpenCVFrameConverter.ToMat();
Frame frame = img2frameConv.convert(image);
Mat mat = frame2matConv.convert(frame);
return mat;
}

public static IplImage convertToIplImage(Mat image) {
OpenCVFrameConverter.ToIplImage img2frameConv = new OpenCVFrameConverter.ToIplImage();
OpenCVFrameConverter.ToMat frame2matConv = new OpenCVFrameConverter.ToMat();
Frame frame = frame2matConv.convert(image);
IplImage img = img2frameConv.convert(frame);
return img;
}
}
17 changes: 6 additions & 11 deletions src/main/java/org/sikuli/core/cv/ImagePreprocessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,27 @@
public class ImagePreprocessor {

public static IplImage createLab(BufferedImage input){
IplImage color = IplImage.createFrom(input);
IplImage color = ImageConverter.convert(input);
IplImage rgb = IplImage.create(cvGetSize(color), 8, 3);
cvCvtColor(color,rgb,CV_BGRA2RGB);
IplImage lab = IplImage.createCompatible(rgb);
IplImage lab = IplImage.createCompatible(rgb);
cvCvtColor(rgb, lab, CV_RGB2Lab );
return lab;
}

public static IplImage createHSV(BufferedImage input){
IplImage color = IplImage.createFrom(input);
IplImage color = ImageConverter.convert(input);
IplImage rgb = IplImage.create(cvGetSize(color), 8, 3);
cvCvtColor(color,rgb,CV_BGRA2RGB);
IplImage hsv = IplImage.createCompatible(rgb);
IplImage hsv = IplImage.createCompatible(rgb);
cvCvtColor(rgb, hsv, CV_RGB2HSV );
return hsv;
}

public static IplImage createGrayscale(BufferedImage input) {
// covert to grayscale at Java level
// something is not right at JavaCV if a ARGB image is given
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorConvertOp op = new ColorConvertOp(cs, null);
BufferedImage gray1 = op.filter(input,null);
return VisionUtils.createGrayImageFrom(IplImage.createFrom(gray1));
return VisionUtils.createGrayImageFrom(input);
}

public static IplImage createGrayscale(IplImage input) {
return VisionUtils.createGrayImageFrom(input);
}
Expand Down
51 changes: 39 additions & 12 deletions src/main/java/org/sikuli/core/cv/VisionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static org.bytedeco.javacpp.opencv_core.cvSetImageCOI;
import static org.bytedeco.javacpp.opencv_core.cvSubRS;
import static org.bytedeco.javacpp.opencv_imgproc.CV_BGR2GRAY;
import static org.bytedeco.javacpp.opencv_imgproc.CV_BGRA2GRAY;
import static org.bytedeco.javacpp.opencv_imgproc.CV_CHAIN_APPROX_SIMPLE;
import static org.bytedeco.javacpp.opencv_imgproc.CV_RETR_EXTERNAL;
import static org.bytedeco.javacpp.opencv_imgproc.CV_SHAPE_RECT;
Expand All @@ -38,6 +39,8 @@
import org.bytedeco.javacpp.opencv_core.CvSeq;
import org.bytedeco.javacpp.opencv_core.IplConvKernel;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.sikuli.core.draw.BlobPainter;
import org.sikuli.core.logging.ImageExplainer;

Expand Down Expand Up @@ -94,20 +97,45 @@ static public void negate(IplImage src, IplImage dest){
cvSubRS(src, cvScalarAll(255), dest, null);
}

static public IplImage createGrayImageFrom(IplImage input){

static public IplImage createGrayImageFrom(BufferedImage image){
IplImage input = ImageConverter.convert(image);
if (input.nChannels() == 3) {
IplImage gray = IplImage.create(cvGetSize(input), input.depth(), 1);
cvCvtColor(input, gray, CV_BGR2GRAY);
return gray;
}else if (input.nChannels() == 4) {
IplImage gray = IplImage.create(cvGetSize(input), input.depth(), 1);
cvCvtColor(input, gray, CV_BGRA2GRAY);
return gray;
}else if (input.nChannels() == 2) {
IplImage gray = IplImage.create(cvGetSize(input), 8, 1);
IplImage alpha = IplImage.create(cvGetSize(input), 8, 1);
IplImage white = IplImage.create(cvGetSize(input), 8, 1);
cvSet(white, CvScalar.WHITE);
cvSetImageCOI(input,1);
cvCopy(input, gray);
cvSetImageCOI(input,2);
cvCopy(input, alpha);
cvCopy(gray,white,alpha);
return white;
}else {
return input;
}
}

static public IplImage createGrayImageFrom(IplImage input){
//System.out.println("nChannels:" + input.nChannels());

if (input.nChannels() == 3){
IplImage gray = IplImage.create(cvGetSize(input), 8, 1);
IplImage gray = IplImage.create(cvGetSize(input), input.depth(), 1);
cvCvtColor(input, gray, CV_BGR2GRAY);
return gray;
}else if (input.nChannels() == 4){
IplImage gray = IplImage.create(cvGetSize(input), 8, 1);
cvSetImageCOI(input,3);
cvCopy(input, gray);//cvCvtColor(input, gray, CV_BGR2GRAY);
cvSetImageCOI(input,0);
return gray;
}else if (input.nChannels() == 2){
IplImage gray = IplImage.create(cvGetSize(input), input.depth(), 1);
cvCvtColor(input, gray, CV_BGRA2GRAY);
return gray;
}else if (input.nChannels() == 2){
IplImage gray = IplImage.create(cvGetSize(input), 8, 1);
IplImage alpha = IplImage.create(cvGetSize(input), 8, 1);
IplImage white = IplImage.create(cvGetSize(input), 8, 1);
Expand Down Expand Up @@ -170,10 +198,9 @@ static public BufferedImage paintBlobsOnImage(BufferedImage image, List<CvRect>
}

public static IplImage cloneWithoutAlphaChannel(IplImage bgra){

IplImage bgr = IplImage.create(bgra.width(), bgra.height(), 8, 3);
IplImage alpha = IplImage.create(bgra.width(), bgra.height(), 8, 1);

IplImage bgr = IplImage.create(bgra.width(), bgra.height(), bgra.depth(), 3);
IplImage alpha = IplImage.create(bgra.width(), bgra.height(), bgra.depth(), 1);

//cvSet(rgba, cvScalar(1,2,3,4));

IplImage[] in = {bgra};
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/sikuli/core/logging/ImageExplainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import javax.imageio.ImageIO;

import org.sikuli.core.cv.ImageConverter;
import org.sikuli.core.draw.ImageRenderer;

import edu.umd.cs.piccolo.PCanvas;
Expand Down Expand Up @@ -168,7 +169,7 @@ public void setLevel(Level level){
}

public void result(IplImage image, Object message){
result(image.getBufferedImage(),message);
result(ImageConverter.convert(image),message);
}

public void step(ImageRenderer producer, Object message){
Expand All @@ -184,7 +185,7 @@ public void result(ImageRenderer producer, Object message){
}

public void step(IplImage image, Object message){
step(image.getBufferedImage(),message);
step(ImageConverter.convert(image),message);
}

public void step(BufferedImage image, Object message){
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/org/sikuli/core/search/TemplateMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,30 @@ public static List<Result> findMatchesByGrayscaleAtOriginalResolution(BufferedIm
return result;
}

public static List<Result> findMatchesByGrayscaleAtOriginalResolution(BufferedImage input, IplImage target, int limit, double minScore){
IplImage input1 = ImagePreprocessor.createGrayscale(input);
IplImage target1 = ImagePreprocessor.createGrayscale(target);
IplImage resultMatrix = TemplateMatchingUtilities.computeTemplateMatchResultMatrix(input1, target1);
List<Result> result = fetchMatches(resultMatrix, target1, limit, minScore);
input1.release();
target1.release();
resultMatrix.release();
return result;
}

// Experimental
public static List<Result> findMatchesByGrayscaleAtOriginalResolutionWithROIs(
BufferedImage input, BufferedImage target, int limit, double minScore, List<Rectangle> rois){
BufferedImage input, BufferedImage target, int limit, double minScore, List<Rectangle> rois){
IplImage input1 = ImagePreprocessor.createGrayscale(input);
IplImage target1 = ImagePreprocessor.createGrayscale(target);
IplImage target1 = ImagePreprocessor.createGrayscale(target);
IplImage resultMatrix = TemplateMatchingUtilities.computeTemplateMatchResultMatrixWithMultipleROIs(input1, target1, rois);
return fetchMatches(resultMatrix, target1, limit, minScore);
}

public static List<Result> findMatchesByGrayscaleAtOriginalResolutionWithROIs(
BufferedImage input, IplImage target, int limit, double minScore, List<Rectangle> rois){
IplImage input1 = ImagePreprocessor.createGrayscale(input);
IplImage target1 = ImagePreprocessor.createGrayscale(target);
IplImage resultMatrix = TemplateMatchingUtilities.computeTemplateMatchResultMatrixWithMultipleROIs(input1, target1, rois);
return fetchMatches(resultMatrix, target1, limit, minScore);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;

import org.bytedeco.javacpp.*;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.List;

import org.sikuli.core.cv.ImageConverter;
import org.sikuli.core.logging.ImageExplainer;

public class TemplateMatchingUtilities {
Expand Down Expand Up @@ -41,7 +43,7 @@ public static IplImage computeTemplateMatchResultMatrix(IplImage input, IplImage
static BufferedImage visualizeResultMatrix(IplImage result){
IplImage resultToShow = IplImage.create(cvGetSize(result), 8, 1);
cvConvertScale(result, resultToShow, 255, 0);
return resultToShow.getBufferedImage();
return ImageConverter.convert(resultToShow);
}

public static IplImage computeTemplateMatchResultMatrixWithMultipleROIs(IplImage input, IplImage target, List<Rectangle> ROIs){
Expand Down