Compare images with MarvinFramework - java

I am trying to determine differences between two images during an integration test. After doing some research on the web, I stumbled over the MarvinProject and tried to create a UnitTest with it, see below.
As far as I understood the plugin DifferentRegions, it will fill the passed ImageMask differenceMask with the regions that contain the differences. The two images I pass for the test do differ, so it should print out something.
Unfortunately it does not.
I have written other tests that compare those two images byte-wise and those succeed. For those who want to try the problem, I have created a repository on GitHub and here is the ImageCompareTest.
#Test
public void tryMarvinProject() {
// init images
String root = "src/test/resources/";
MarvinImage assertedImg = MarvinImageIO.loadImage(root + "image1.bmp");
MarvinImage actualImg = MarvinImageIO.loadImage(root + "image2.bmp");
// init diff-regions plugin
DifferentRegions regions = new DifferentRegions();
regions.load();
regions.setAttribute("comparisonImage", assertedImg);
int width = assertedImg.getWidth();
int height = assertedImg.getHeight();
int type = assertedImg.getType();
// process the images and retrieve differences from the ImageMask
MarvinImageMask differenceMask = new MarvinImageMask();
regions.process(
actualImg,
new MarvinImage(new BufferedImage(width, height, type)),
new MarvinAttributes(),
differenceMask,
false);
// should contain the differences, but does not
System.out.println(differenceMask.getMaskArray());
assertNotNull(differenceMask.getMaskArray());
}

The plug-in DifferentRegions was developed for real-time video processing. The idea is to find the regions in the scene which are changing in a sequence of video frames, as shown in this Example
For image-to-image comparison, you should try DifferenceColor plug-in. Basically, it compare the two images analysing the color intensity of pixels in the same position. If the difference of two given pixels is higher than the attribute colorRange, the two pixels are considered distinct in color. The plug-in renders the different pixels in a different color to show them in the output image. If you pass an MarvinAttributes object in the process(...) method, you can get the number of different pixels, stored in the key total.
Example:
MarvinAttributes attrOut = new MarvinAttributes();
MarvinImagePlugin diff = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.difference.differenceColor");
diff.process(imageA, imageB, attrOut);
System.out.println("Distinct pixels:"+attrOut.get("total"));
PS: In order to use MarvinPluginLoader you must configure the development environment following the instructions presented here.
However, since you are trying to use image comparison for Unit Testing, you should take a look at MarvinTestCase class. It extends JUnit TestCase and provide methods to compare MarvinImage objects.
Input:
The source code below implements two test cases, one comparing imageA to imageB, and the other comparing imageA to imageC.
import marvin.image.MarvinImage;
import marvin.io.MarvinImageIO;
import marvin.test.MarvinTestCase;
public class UnitTesting extends MarvinTestCase {
private MarvinImage imageA, imageB, imageC;
public UnitTesting(){
imageA = MarvinImageIO.loadImage("./res/penguin.jpg");
imageB = MarvinImageIO.loadImage("./res/penguin.jpg");
imageC = MarvinImageIO.loadImage("./res/penguin_dark.jpg");
}
public void testSameImage(){
assertEquals(imageA, imageB);
}
public void testDistinctImages(){
assertEquals(imageA, imageC);
}
}
Using Eclipse or another IDE, run the class above as a JUnit Test. Below the output in the JUnit tab on Eclipse.

Related

Matching images from file with Sikuli

I just found about Sikuli when I was looking for a library to find matches of a given image within a larger image (both loaded from files).
By default, Sikuli only supports loading the searched image from file, but relies on a proprietary class Screen to take screenshots to use as base for the search... And I'd like to have the ability to use a image file instead.
Looking for a solution has led me to this question, but the answer is a bit vague when you consider that I have no prior experience with Sikuli and the available documentation is not particularly helpful for my needs.
Does anyone have any examples on how to make a customized implementation of Screen, ScreenRegion, ImageScreen and ImageScreenLocation? Even a link to a more detailed documentation on these classes would be a big help.
All I want is to obtain the coordinates of an image match within another image file, so if there's another library that could help with this task I'd more than happy to learn about it!
You can implement it by yourself with something like this:
class MyImage{
private BufferedImage img;
private int imgWidth;
private int imgHeight;
public MyImage(String imagePath){
try{
img = ImageIO.read(getClass().getResource(imagePath));
}catch(IOException ioe){System.out.println("Unable to open file");}
init();
}
public MyImage(BufferedImage img){
this.img = img;
init();
}
private void init(){
imgWidth = img.getWidth;
imgHeight = img.getHeight();
}
public boolean equals(BufferedImage img){
//Your algorithm for image comparison (See below desc for your choices)
}
public boolean contains(BufferedImage subImage){
int subWidth = subImage.getWidth();
int subHeight = subImage.getHeight();
if(subWidth > imgWidth || subHeight > imgHeight)
throw new IllegalArgumentException("SubImage is larger than main image");
for(int x=0; x<(imgHeight-subHeight); x++)
for(int y=0; y<(imgWidth-subWidth); y++){
BufferedImage cmpImage = img.getSumbimage(x, y, subWidth, subHeight);
if(subImage.equals(cmpImage))
return true;
}
return false;
}
}
The contains method will grab a subimage from the main image and compare with the given subimage. If it is not the same, it will move on to the next pixel until it went through the entire image. There might be other more efficient ways than moving pixel by pixel, but this should work.
To compare 2 images for similarity
You have at least 2 options:
Scan pixel by pixel using a pair of nested loop to compare the RGB value of each pixel. (Just like how you compare two int 2D array for similarity)
It should be possible to generate a hash for the 2 images and just compare the hash value.
Aah... Sikuli has an answer for this too... You just didnt look close enough. :)
Answer : The FINDER Class
Pattern searchImage = new Pattern("abc.png").similar((float)0.9);
String ScreenImage = "xyz.png"; //In this case, the image you want to search
Finder objFinder = null;
Match objMatch = null;
objFinder = new Finder(ScreenImage);
objFinder.find(searchImage); //searchImage is the image you want to search within ScreenImage
int counter = 0;
while(objFinder.hasNext())
{
objMatch = objFinder.next(); //objMatch gives you the matching region.
counter++;
}
if(counter!=0)
System.out.println("Match Found!");
In the end I gave up on Sikuli and used pure OpenCV in my Android project: The Imgproc.matchTemplate() method did the trick, giving me a matrix of all pixels with "scores" for the likehood of that being the starting point of my subimage.
With Sikuli, you can check for the presence of an image inside another one.
In this example code, the pictures are loaded from files.
This code tell us if the second picture is a part of the first picture.
public static void main(String[] argv){
String img1Path = "/test/img1.png";
String img2Path = "/test/img2.png";
if ( findPictureRegion(img1Path, img2Path) == null )
System.out.println("Picture 2 was not found in picture 1");
else
System.out.println("Picture 2 is in picture 1");
}
public static ScreenRegion findPictureRegion(String refPictureName, String targetPictureName2){
Target target = new ImageTarget(new File(targetPictureName2));
target.setMinScore(0.5); // Precision of recognization from 0 to 1.
BufferedImage refPicture = loadPicture(refPictureName);
ScreenRegion screenRegion = new StaticImageScreenRegion(refPicture);
return screenRegion.find(target);
}
public static BufferedImage loadPicture(String pictureFullPath){
try {
return ImageIO.read(new File(pictureFullPath));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
To use Sikuli package, I added this dependency with Maven :
<!-- SIKULI libraries -->
<dependency>
<groupId>org.sikuli</groupId>
<artifactId>sikuli-api</artifactId>
<version>1.1.0</version>
</dependency>

Java - Create world collision with Heightmap (JBullet)

I'm trying to create an infinite playable world with Jogl, Jbullet, and OpenSimplexNoise (OSN).
I'm generating the world with OSN, rendering it successfully, but I don't know how to add it to the world/collision system.
I found the btHeightfieldTerrainShape class, but it isn't implemented in Java.
I tried to use BvhTriangleMeshShape too, but i don't understand how it work.
I have 3 values of generation:
int smooth: the number of division in one meter
int viewDistance: the number of chunk to draw in one axis
int chunkSize: the number on
meter in one chunk
I'm using this code for generate heightmap:
/**
* Generate all height in the chunk p[cx][cy].
*/
private float[][] genPerlinMap(int[] p) {
float[][] pts = new float[chunkSize*smooth+1][chunkSize*smooth+1];
for(int i1=0;i1<chunkSize*smooth+1;i1++){
for(int i2=0;i2<chunkSize*smooth+1;i2++){
pts[i1][i2] = (float) (osp.eval(
(p[0]*chunkSize+i1/(float)(smooth))/(float) (mapSize),
(p[1]*chunkSize+i2/(float)(smooth))/(float) (mapSize)
)+1)*0.5f*mapSize;
}
}
return pts;
}
Does someone know how to add this ?
I found a solution: use https://github.com/bubblecloud/jbullet (jbullet from github) with the code here: https://github.com/bubblecloud/jbullet/commit/a5da8cdc679e998ef3a8605ee9b3cd5f94d71fee .
Thanks gouessej for the jbullet github link :)

LibGDX - find out if a given screen resolution is supported on the current device

So I'm writing some tools for my program to deal with basic configurations, reading settings from a data file, and then making those settings the active configuration. I'm also building in an error checking mechanism to make sure that settings are formatted correctly and have valid values.
I want to check to see what the current devices supported resolutions are, and I want to compare that to the resolution specified in the data file. Is there an easy way to do this in libGDX that I'm missing? I know that LWJGL has a function that will give you an array of the supported resolutions, but I don't want to reinvent the wheel.
I'm looking for something like:
boolean isValidResolutionForDevice(int width, int height)
Am I going to have to write this myself? Or does this exist already? It seems to me to be such a useful function that it must have been written into the libraries somewhere.
There actually is a way to do this. The main com.badlogic.gdx.Application interface has a getGraphics() method, and the com.badlogic.gdx.Graphics class returned from that has getDisplayModes() method, which returns DisplayMode[]. DisplayMode basically looks like this (comments and constructor removed):
public class DisplayMode {
/** the width in physical pixels **/
public final int width;
/** the height in physical pixles **/
public final int height;
/** the refresh rate in Hertz **/
public final int refreshRate;
/** the number of bits per pixel, may exclude alpha **/
public final int bitsPerPixel;
}
And then you can scan through these to see if the resolution in question is supported or not.
The only bit of annoying news is because getGraphics() is on the Application object, it doesn't seem like you can query for the available graphics modes until after the Application object (e.g. LwjglApplication) has been created. So perhaps you pick an arbitrary resolution (e.g. 1024x768), start the game, then immediately switch to a supported resolution if the original wasn't actually supported (and optionally let the user pick in a settings menu).
I came across the method I believe you're referring to, org.lwjgl.opengl.Display.getAvailableDisplayModes(), and...honestly I'd just use this one for your use case. You'd pretty much just be iterating over it with a simple conditional inside. Not exactly reinventing anything.
Unfortunately, there is no ready solution in libgdx, I solved it like this:
private Map<Integer, Integer> supportedReolutions;
private String graphicFolder;
supportedReolutions = new HashMap<Integer, Integer>();
supportedReolutions.put(1024, 768);
supportedReolutions.put(1080, 1920);
supportedReolutions.put(1200, 1920);
supportedReolutions.put(2048, 1536);
supportedReolutions.put(480, 800);
supportedReolutions.put(640, 1136);
graphicFolder = "1080x1920";
/**
* Chose the folder with best graphic for current device
*/
private void setCurrentResolutionFolder() {
int width = Gdx.graphics.getWidth();
int height = Gdx.graphics.getHeight();
if (supportedReolutions.containsKey(width)) {
if (supportedReolutions.get(width) == height) {
graphicFolder = String.valueOf(width) + "x"
+ String.valueOf(height);
}
}
}

Recognizing numbers in an image in java

I want to recognize numbers in the following image
I am currently using Tess4J library in eclipse java project but it only recognizes the characters in a plane color background. For this image it could not even identify that there are characters(numbers) on this image. Help me find a way to accomplish this task.
Here is my current code:
import net.sourceforge.tess4j.*;
import java.io.File;
public class Main {
public static void main(String[] args) {
File imageFile = new File("image.png");
Tesseract instance = Tesseract.getInstance();
try {
String result = instance.doOCR(imageFile);
System.out.println(result);
} catch (TesseractException e) {
System.err.println(e.getMessage());
}
}
}
and if there is way to count the squares separated by yellow lines.
Thank you
If your image is representative, then all you need as a first step is a binarization at a threshold close to the maximum value followed by discarding of small components.
f = Import["http://i.stack.imgur.com/6AXwH.jpg"]
step1 = SelectComponents[Binarize[ColorConvert[f, "Grayscale"], 0.9],
"Count", #1 > 100 &]
Now, if you know that the digits cannot be too tall or too thin (this is dependent on image dimensions), then you can filter the remaining components based on its bounding box.
SelectComponents[step1, "BoundingBox",
And[10 < #[[2, 1]] - #[[1, 1]] < 100, 50 < #[[2, 2]] - #[[1, 2]] < 100] &]
To separate each of the regions, you could consider using a colorspace where there is a channel dedicated to the yellow color. CMYK is a possibility here, and again all you need is a threshold at a high value, together with the basic morphological closing to complete the lines (since in your example the lines do not extend to the border of the image). Instead of using morphological closings here, you could detect the lines using Hough or RANSAC, for example.
rects = Closing[
Closing[Binarize[ColorSeparate[f, "CMYK"][[3]], 0.9],
ConstantArray[1, {1, 15}]], ConstantArray[1, {15, 1}]] (* left image *)
Colorize[MorphologicalComponents[ColorNegate[rects]],
ColorFunction -> "Rainbow"] (* right image *)
The tools used here are very simple, and almost any image processing library will provide them. There are also more robust approaches that could be taken, but for the given image it is not needed.

Mouse shows color

i am trying to make an application which would show which color my mouse is pointing to, i dont mean in my own application but anywhere in windows on any screen, kind of like a tag beside my mouse pointer which shows the exact color.
I am a Java developer but i dont think this could be done in java i am thinking maybe i need some sort of script but i have no idea any help would be really appriciated
The solution consists of two parts:
Part 1: Retrieving the color:
Point mouseLocation = MouseInfo.getPointerInfo().getLocation();
Color color = new Robot().getPixelColor(mouseLocation.x, mouseLocation.y);
Part 2: Getting the color name:
You can get a list of many colors and their names from Wikipedia's List of colors. You can create a mapping in Java given the data on Wikipedia.
Perhaps you can start with a few colors, and provide a generic hex representation for unknown colors, for example #rrggbb.
Here is the runnable example,
import java.awt.AWTException;
import java.awt.Color;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
public class Main {
public static String getHexString(int rgb) {
String hexString = Integer.toHexString(rgb);
hexString = hexString.length() > 1 ? hexString : "0" + hexString;
return hexString;
}
public static void main(String[] a) throws AWTException {
Point mouseLocation = MouseInfo.getPointerInfo().getLocation();
Color color = new Robot().getPixelColor(mouseLocation.x,
mouseLocation.y);
System.out.println(getHexString(color.getRed())
+ getHexString(color.getGreen())
+ getHexString(color.getBlue()));
}
}
Take your pick: http://rosettacode.org/wiki/Color_of_a_screen_pixel
There is a Java/AWT example, an AutoHotKey is a simple scripted option.
The second C example shows the 3 API calls you need GetDC/GetCursorPos/GetPixel and their support code, these can be used from most languages that compile for windows.

Categories