Text extraction and segmentation open CV - java

I've never used OpenCV before, but I'm trying to write my neural network system to recognize text and I need some tool for text extraction/ segmentation.
How can I use java OpenCV to preprocess and segmentate an image containing text.I don't need to recognize the text, I just need to get each letter in a separate image.
Something like this :

Try this code .No need of OpenCV
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import org.neuroph.imgrec.ImageUtilities;
public class CharExtractor {
private int cropTopY = 0;//up locked coordinate
private int cropBottomY = 0;//down locked coordinate
private int cropLeftX = 0;//left locked coordinate
private int cropRightX = 0;//right locked coordinate
private BufferedImage imageWithChars = null;
private boolean endOfImage;//end of picture
private boolean endOfRow;//end of current reading row
/**
* Creates new char extractor with soecified text image
* #param imageWithChars - image with text
*/
public CharExtractor(BufferedImage imageWithChars) {
this.imageWithChars = imageWithChars;
}
public void setImageWithChars(BufferedImage imageWithChars) {
this.imageWithChars = imageWithChars;
}
/**
* This method scans image pixels until it finds the first black pixel (TODO: use foreground color which is black by default).
* When it finds black pixel, it sets cropTopY and returns true. if it reaches end of image and does not find black pixels,
* it sets endOfImage flag and returns false.
* #return - returns true when black pixel is found and cropTopY value is changed, and false if cropTopY value is not changed
*/
private boolean findCropTopY() {
for (int y = cropBottomY; y < imageWithChars.getHeight(); y++) { // why cropYDown? - for multiple lines of text using cropBottomY from previous line above; for first line its zero
for (int x = cropLeftX; x < imageWithChars.getWidth(); x++) { // scan starting from the previous left crop position - or it shoud be right???
if (imageWithChars.getRGB(x, y) == -16777216) { // if its black rixel (also consider condition close to black or not white or different from background)
this.cropTopY = y; // save the current y coordiante
return true; // and return true
}
}
}
endOfImage = true; //sets this flag if no black pixels are found
return false; // and return false
}
/**
* This method scans image pixels until it finds first row with white pixels. (TODO: background color which is white by default).
* When it finds line whith all white pixels, it sets cropBottomY and returns true
* #return - returns true when cropBottomY value is set, false otherwise
*/
private boolean findCropBottomY() {
for (int y = cropTopY + 1; y < imageWithChars.getHeight(); y++) { // scan image from top to bottom
int whitePixCounter = 0; //counter of white pixels in a row
for (int x = cropLeftX; x < imageWithChars.getWidth(); x++) { // scan all pixels to right starting from left crop position
if (imageWithChars.getRGB(x, y) == -1) { // if its white pixel
whitePixCounter++; // increase counter
}
}
if (whitePixCounter == imageWithChars.getWidth()-1) { // if we have reached end of line counting white pixels (x pos)
cropBottomY = y;// that means that we've found white line, so set current y coordinate minus 1
return true; // as cropBottomY and finnish with true
}
if (y == imageWithChars.getHeight() - 1) { // if we have reached end of image
cropBottomY = y; // set crop bottom
endOfImage = true; // set corresponding endOfImage flag
return true; // and return true
}
}
return false; // this should never happen, however its possible if image has non white bg
}
private boolean findCropLeftX() {
int whitePixCounter = 0; // white pixel counter between the letters
for (int x = cropRightX; x < imageWithChars.getWidth(); x++) { // start from previous righ crop position (previous letter), and scan following pixels to the right
for (int y = cropTopY; y <= cropBottomY; y++) { // vertical pixel scan at current x coordinate
if (imageWithChars.getRGB(x, y) == -16777216) { // when we find black pixel
cropLeftX = x; // set cropLeftX
return true; // and return true
}
}
// BUG?: this condition looks strange.... we might not need whitePixCounter at all, it might be used for 'I' letter
whitePixCounter++; // if its not black pixel assume that its white pixel
if (whitePixCounter == 3) { // why 3 pixels? its hard coded for some case and does not work in general...!!!
whitePixCounter = 0; // why does it sets to zero, this has no purporse at all...
}
}
endOfRow = true; // if we have reached end of row and we have not found black pixels, set the endOfRow flag
return false; // and return false
}
/**
* This method scans image pixels to the right until it finds next row where all pixel are white, y1 and y2.
* #return - return true when x2 value is changed and false when x2 value is not changed
*/
private boolean findCropRightX() {
for (int x = cropLeftX + 1; x < imageWithChars.getWidth(); x++) { // start from current cropLeftX position and scan pixels to the right
int whitePixCounter = 0;
for (int y = cropTopY; y <= cropBottomY; y++) { // vertical pixel scan at current x coordinate
if (imageWithChars.getRGB(x, y) == -1) { // if we have white pixel at current (x, y)
whitePixCounter++; // increase whitePixCounter
}
}
// this is for space!
int heightPixels = cropBottomY - cropTopY; // calculate crop height
if (whitePixCounter == heightPixels+1) { // if white pixel count is equal to crop height+1 then this is white vertical line, means end of current char/ (+1 is for case when there is only 1 pixel; a 'W' bug fix)
cropRightX = x; // so set cropRightX
return true; // and return true
}
// why we need this when we allready have condiiton in the for loop? - for the last letter in the row.
if (x == imageWithChars.getWidth() - 1) { // if we have reached end of row with x position
cropRightX = x; // set cropRightX
endOfRow = true; // set endOfRow flag
return true; // and return true
}
}
}
public List<BufferedImage> extractCharImagesToRecognize() {
List<BufferedImage> trimedImages = new ArrayList<BufferedImage>();
int i = 0;
while (endOfImage == false) {
endOfRow = false;
boolean foundTop = findCropTopY();
boolean foundBottom = false;
if (foundTop == true) {
foundBottom = findCropBottomY();
if (foundBottom == true) {
while (endOfRow == false) {
boolean foundLeft = false;
boolean foundRight = false;
foundLeft = findCropLeftX();
if (foundLeft == true) {
foundRight = findCropRightX();
if (foundRight == true) {
BufferedImage image = ImageUtilities.trimImage(ImageUtilities.cropImage(imageWithChars, cropLeftX, cropTopY, cropRightX, cropBottomY));
trimedImages.add(image);
i++;
}
}
}
cropLeftX = 0;
cropRightX = 0;
}
}
}
cropTopY = 0;
cropBottomY = 0;
endOfImage = false;
return trimedImages;
}
public static void main(String[] args) throws Exception {
File f=new File("./written.png");
BufferedImage img=ImageIO.read(f);
CharExtractor ch=new CharExtractor(img);
List<BufferedImage> list=ch.extractCharImagesToRecognize();
for(int i=0;i<list.size();i++)
{
File outputfile = new File("./char_" +i+ ".png");
ImageIO.write(list.get(i),"png", outputfile);
}
}
}

What you are trying to do is a general scene text localization problem, and it's pretty difficult. Check out this article for inspiration - http://www.maseltov.eu/wp-content/uploads/2014/02/CTU-03_Real-Time-Scene-Text-Localization-and-Recognition.pdf
What you could do is:
write a program which extracts MSER objects from an image
extract features from every patch determined by each individual MSER (which features is outlined in the article)
train your classifier (in your case a neural network I guess?) so that it is able to distinguish between character and non-character regions
write a program which uses your classifier to extract MSERs and classify them using the trained NN.
The MSER algorithm is implemented in OpenCV, so that is a plus. There are also neural network classifiers there, but since I only used SVM, I can not comment on that too much. I should say that we had to solve this problem as well and it is perfectly possible to do so using OpenCV. Just don't expect to get everything on a silver platter - there is a lot of work involved; especially when choosing and extracting the blob features.

I am not familiar with neural networks, but if you just want to find letters in an image with respecting scale and rotation, I can recommend this Project http://www.codeproject.com/Articles/196168/Contour-Analysis-for-Image-Recognition-in-C
It is written in C#, but you could port it to java or at least get a good amount of insights on this topic.

Related

Algorithm to get all pixels between color border?

I have a long png file containing many sprites in a row, but their width/height changes by a little bit. However, all sprites have a fixed blue color 1px border around it.
However, after each sprite, the borders are connected to each other by 2px (just border after border that interacts) see this:
But at the bottom of the sprites, it misses one pixel point
Is there an existing algorithm that can get all pixels between a color border like this, including the border when giving the pixels?
Or any other ideas how to grab all sprites of one file like this and give them a fixed size?
I took your image and transformed it to match your description.
In plain text I went form left to right and identify lines that might indicate a start or end to an image and used a tracker variable to decide which is which.
I approached it like this in Java:
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.io.IOException;
public class PixelArtSizeFinder {
public static void main(String[] args) throws IOException {
File imageFile = new File("pixel_boat.png");
BufferedImage image = ImageIO.read(imageFile);
int w = image.getWidth();
int h = image.getHeight();
System.out.format("Size: %dx%d%n", w, h);
Raster data = image.getData();
int objectsFound = 0;
int startObjectWidth = 0;
int endObjectWidth = 0;
boolean scanningObject = false;
for (int x = 0; x < w; x++) {
boolean verticalLineContainsOnlyTransparentOrBorder = true;
for (int y = 0; y < h; y++) {
int[] pixel = data.getPixel(x, y, new int[4]);
if (isOther(pixel)) {
verticalLineContainsOnlyTransparentOrBorder = false;
}
}
if (verticalLineContainsOnlyTransparentOrBorder) {
if (scanningObject) {
endObjectWidth = x;
System.out.format("Object %d: %d-%d (%dpx)%n",
objectsFound,
startObjectWidth,
endObjectWidth,
endObjectWidth - startObjectWidth);
} else {
objectsFound++;
startObjectWidth = x;
}
scanningObject ^= true; //toggle
}
}
}
private static boolean isTransparent(int[] pixel) {
return pixel[3] == 0;
}
private static boolean isBorder(int[] pixel) {
return pixel[0] == 0 && pixel[1] == 187 && pixel[2] == 255 && pixel[3] == 255;
}
private static boolean isOther(int[] pixel) {
return !isTransparent(pixel) && !isBorder(pixel);
}
}
and the result was
Size: 171x72
Object 1: 0-27 (27px)
Object 2: 28-56 (28px)
Object 3: 57-85 (28px)
Object 4: 86-113 (27px)
Object 5: 114-142 (28px)
Object 6: 143-170 (27px)
I don't know if any algorithm or function already exists for this but what you can do is :
while the boats are all the same and you wanna get all the pixels between two blue pixels so you can use something like this :
for all i in vertical pixels
for all j in horizontal pixels
if pixel(i,j) == blue then
j = j+ 1
while pixel(i,j) != blue then
you save this pixel in an array for example
j = j+1
end while
end if
end for
end for
This is just an idea and for sure not the most optimal but you can you use it and perform it to make it better ;)

LibGDX - Map Boundaries

Synopsis
Well, I'm making a little top-down JRPG and today I was like 'Yeah, I'm gonna bust out this whole map collision thing!'. I failed.
Problem
So I went on the internet and looked up 'LibGDX Tiled Map Collision Detection' and found a really neat post about Map Objects so I added in a map object layer and did all that biz and came out with this little method to ensure the player can move freely around the map but at the same time can't exit it but each time I've tried it ends up with a horrible result such as the player moving off the screen. The latest error is that the player gets stuck doing a walk animation and can't move anywhere else!
Code
package com.darkbyte.games.tfa.game.entity.entities;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.math.Rectangle;
import com.darkbyte.games.tfa.game.entity.Entity;
import com.darkbyte.games.tfa.game.entity.SpriteSheet;
import com.darkbyte.games.tfa.game.world.map.MapManager;
import com.darkbyte.games.tfa.render.Batch;
import com.darkbyte.games.tfa.render.Camera;
public class Player extends Entity {
// The constructor for the player class
public Player(String name, SpriteSheet spriteSheet) {
super(name, spriteSheet);
direction = Direction.DOWN;
collisionBox = new Rectangle(x, y, 64, 64);
}
// A flag to see if the player is moving
private boolean isMoving;
// The variable that holds the state time
private float stateTime;
// The player's walking animations
private Animation[] walkAnimations = {
spriteSheet.getAnimation(8, 8, 1 / 16f),
spriteSheet.getAnimation(9, 8, 1 / 16f),
spriteSheet.getAnimation(10, 8, 1 / 16f),
spriteSheet.getAnimation(11, 8, 1 / 16f) };
// The player's static frames
private TextureRegion[] staticFrames = {
spriteSheet.getTexture(8, 0),
spriteSheet.getTexture(9, 0),
spriteSheet.getTexture(10, 0),
spriteSheet.getTexture(11, 0) };
// The render code for the player
#Override
public void render() {
// Makes the camera follow the player
Camera.setCameraPosition(x, y);
Batch.getGameBatch().setProjectionMatrix(Camera.getCamera().combined);
// Updates the state time
stateTime += Gdx.graphics.getDeltaTime();
// Gets the player's direction, if the player's moving, it sets the
// current frame to the frame that would be played at the current moment
// based on the state time
// If the player isn't moving, it sets the current frame to the static
// frame associated to the direction
switch (direction) {
case UP:
if(isMoving) {
currentFrame = walkAnimations[0].getKeyFrame(stateTime, true);
} else
currentFrame = staticFrames[0];
break;
case LEFT:
if(isMoving) {
currentFrame = walkAnimations[1].getKeyFrame(stateTime, true);
} else
currentFrame = staticFrames[1];
break;
case DOWN:
if(isMoving) {
currentFrame = walkAnimations[2].getKeyFrame(stateTime, true);
} else
currentFrame = staticFrames[2];
break;
case RIGHT:
if(isMoving) {
currentFrame = walkAnimations[3].getKeyFrame(stateTime, true);
} else
currentFrame = staticFrames[3];
break;
}
}
// The tick code for the player
#Override
public void tick() {
// The object to represent the bounds of the land on the map
RectangleMapObject land = (RectangleMapObject) MapManager.getCurrentMap().getMap().getLayers().get("collision").getObjects().get("land");
// Checks if the player is within the bounds of the map
if(land.getRectangle().contains(collisionBox)) {
// If the player is moving but the arrow keys aren't pressed, sets isMoving to false
isMoving = (isMoving && (Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP)
|| Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)
|| Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN)
|| Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT)));
// Checks to see if the arrow / WASD keys are pressed and moves the
// player in the correct direction at the speed of 1.5 pixels/tick
// (45/second)
// It also sets the players state to moving and corresponds it's
// direction to the key pressed
// Doesn't move if opposing keys are pressed
if(Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP)) {
if(!(Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN))) {
direction = Direction.UP;
y += 1.5f;
isMoving = true;
}
}
if(Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)) {
if(!(Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT))) {
direction = Direction.LEFT;
isMoving = true;
x -= 1.5f;
}
}
if(Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN)) {
if(!(Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP))) {
direction = Direction.DOWN;
y -= 1.5f;
isMoving = true;
}
}
if(Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT)) {
if(!(Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT))) {
direction = Direction.RIGHT;
x += 1.5f;
isMoving = true;
}
}
} else {
if(!isMoving) {
// If the player's just spawned puts the player to the map's spawn point
x = MapManager.getCurrentMap().getPlayerSpawnX();
y = MapManager.getCurrentMap().getPlayerSpawnY();
} else { // If not, it just moves them back till they're no longer out of the map
if(x > (land.getRectangle().getX() + land.getRectangle().getWidth())) x -= 1.5;
if(y > (land.getRectangle().getY() + land.getRectangle().getHeight())) y -= 1.5;
}
}
// Synchronises the collision box with the player's x and y position
collisionBox.x = x;
collisionBox.y = y;
}
// Returns if the player is moving
public boolean isMoving() {
return isMoving;
}
}
Can you guys make it so that when he reaches the border that he stops but he can still keep moving in other directions instead of staying static!
Thanks for reading!
At the moment it sounds you just copy/pasted it and you need to familiarize yourself with it first. If you don't know what it does then you should learn or stop the project imho.
Anyway, from what I can tell it's just a player class that handles the animation frames based on which direction it is moving. Nothing to do with collision detection at all. It does update some kind of collisionBox but functionality for this is handled elsewhere, perhaps in the parent class Entity?
My guess is that this is a tile map and units are restricted to the grid. It's pretty easy to detect if A tile exists or not.
private boolean tileExists(int tileX, int tileY, tile[][] map)
{
return tileX >= 0 && tileY >= 0 &&
tileX < map.length && tileY < map[0].length;
}
Now whenever a entity requests a move you should check if the destination is within the map bounds.
private void moveRequest(int destinationX, int destinationY, Tile[][] map)
{
//Just return if the tile is outside of the map
if (!tileExists(destinationX, destinationY, map) return;
//Same goes for your other checks...
//Return if the tile is not walkable
if (!tileIsWalkable(destinationX, destinationY, map) return;
//Return if the tile is already occupied
if (tileIsOccupied(destinationX, destinationY, otherEntities) return;
//etc..
//Now the move is valid and you can set it's state to moving in that direction.
}
Tile maps are not very hard to understand. I will make an attempt to give you some better insight into tile maps. You have a 2D array where you store your tiles in. Tiles have a width and a height and from that you can make your own tile engine:
//Find out which tiles to draw based on the camera position and viewport size.
int startX = (int)(camera.position.x - camera.viewportWidth / 2) / tileWidth;
int startY = (int)(camera.position.y - camera.viewportHeight / 2) / tileHeight;
int endX = (int)(startX + camera.viewportWidth / tileWidth) + 1;
int endY = (int)(startY + camera.viewportHeight / tileHeight) + 1;
//Loop using this data as boundaries
for (int y = startY; y < endY; y++)
{
for (int x = startX; x < endX; x++)
{
//If out of bounds continue to next tile.
if (!tileExists(x, y, map) continue;
//Now all we need to draw the on screen tiles properly:
//x == tile position x in array
//y == tile position y in array
//World position of this tile:
//worldX = x * tileWidth;
//worldY = y * tileHeight;
//Let's draw:
batch.draw(map[x][y].getTexture, worldX, worldY,
tileWidth, tileHeight)
}
}
There really is no magic involved here at all. Drawing only what is on screen like in the above example is very important for larger maps. Other then that you should draw thing in the back first. You have several options to do this, the easiest but least versatile is just a separate the ground from the objects that can obscure things and draw this later.
Characters, creatures or other entities can just use a world position and be easily converted back to tile position.
tileX = worldX / tileWidth;
tileY = worldY / tileHeight;
So if you want to move something with the world position calculate it's tile position first using the aforementioned method. Then lookup if this tile is valid to move to. Then block that tile for other and move to it.

Breaking bricks with chain reaction

I am developing a game in java just for fun. It is a ball brick breaking game of some sort.
Here is a level, when the ball hits one of the Orange bricks I would like to create a chain reaction to explode all other bricks that are NOT gray(unbreakable) and are within reach of the brick being exploded.
So it would clear out everything in this level without the gray bricks.
I am thinking I should ask the brick that is being exploded for other bricks to the LEFT, RIGHT, UP, and DOWN of that brick then start the same process with those cells.
//NOTE TO SELF: read up on Enums and List
When a explosive cell is hit with the ball it calls the explodeMyAdjecentCells();
//This is in the Cell class
public void explodeMyAdjecentCells() {
exploded = true;
ballGame.breakCell(x, y, imageURL[thickness - 1][0]);
cellBlocks.explodeCell(getX() - getWidth(),getY());
cellBlocks.explodeCell(getX() + getWidth(),getY());
cellBlocks.explodeCell(getX(),getY() - getHeight());
cellBlocks.explodeCell(getX(),getY() + getHeight());
remove();
ballGame.playSound("src\\ballgame\\Sound\\cellBrakes.wav", 100.0f, 0.0f, false, 0.0d);
}
//This is the CellHandler->(CellBlocks)
public void explodeCell(int _X, int _Y) {
for(int c = 0; c < cells.length; c++){
if(cells[c] != null && !cells[c].hasExploded()) {
if(cells[c].getX() == _X && cells[c].getY() == _Y) {
int type = cells[c].getThickness();
if(type != 7 && type != 6 && type != 2) {
cells[c].explodeMyAdjecentCells();
}
}
}
}
}
It successfully removes my all adjacent cells,
But in the explodeMyAdjecentCells() method, I have this line of code
ballGame.breakCell(x, y, imageURL[thickness - 1][0]);
//
This line tells the ParticleHandler to create 25 small images(particles) of the exploded cell.
Tough all my cells are removed the particleHandler do not create particles for all the removed cells.
The problem was solved youst now, its really stupid.
I had set particleHandler to create max 1500 particles. My god how did i not see that!
private int particleCellsMax = 1500;
private int particleCellsMax = 2500;
thx for all the help people, I will upload the source for creating the particles youst for fun if anyone needs it.
The source code for splitting image into parts was taken from:
Kalani's Tech Blog
//Particle Handler
public void breakCell(int _X, int _Y, String URL) {
File file = new File(URL);
try {
FileInputStream fis = new FileInputStream(file);
BufferedImage image = ImageIO.read(fis);
int rows = 5;
int colums = 5;
int parts = rows * colums;
int partWidth = image.getWidth() / colums;
int partHeight = image.getHeight() / rows;
int count = 0;
BufferedImage imgs[] = new BufferedImage[parts];
for(int x = 0; x < colums; x++) {
for(int y = 0; y < rows; y++) {
imgs[count] = new BufferedImage(partWidth, partHeight, image.getType());
Graphics2D g = imgs[count++].createGraphics();
g.drawImage(image, 0, 0, partWidth, partHeight, partWidth * y, partHeight * x, partWidth * y + partWidth, partHeight * x + partHeight, null);
g.dispose();
}
}
int numParts = imgs.length;
int c = 0;
for(int iy = 0; iy < rows; iy ++) {
for(int ix = 0; ix < colums; ix++) {
if(c < numParts) {
Image imagePart = Toolkit.getDefaultToolkit().createImage(imgs[c].getSource());
createCellPart(_X + ((image.getWidth() / colums) * ix), _Y + ((image.getHeight() / rows) * iy), c, imagePart);
c++;
} else {
break;
}
}
}
} catch(IOException io) {}
}
You could consider looking at this in a more OO way, and using 'tell don't ask'. So you would look at having a Brick class, which would know what its colour was, and its adjacent blocks. Then you would tell the first Block to explode, it would then know that if it was Orange (and maybe consider using Enums for this - not just numbers), then it would tell its adjacent Blocks to 'chain react' (or something like that), these blocks would then decide what to do (either explode in the case of an orange block - and call their adjacent blocks, or not in the case of a grey Block.
I know its quite different from what your doing currently, but will give you a better structured program hopefully.
I would imagine a method that would recursively get all touching cells of a similar color.
Then you can operate on that list (of all touching blocks) pretty easily and break all the ones are haven't been broken.
Also note that your getAdjentCell() method has side effects (it does the breaking) which isn't very intuitive based on the name.
// I agree with Matt that color (or type) should probably be an enum,
// or at least a class. int isn't very descriptive
public enum CellType { GRAY, RED, ORANGE }
public class Cell{
....
public final CellType type;
/**
* Recursively find all adjacent cells that have the same type as this one.
*/
public List<Cell> getTouchingSimilarCells() {
List<Cell> result = new ArrayList<Cell>();
result.add(this);
for (Cell c : getAdjecentCells()) {
if (c != null && c.type == this.type) {
result.addAll(c.getTouchingSimilarCells());
}
}
return result;
}
/**
* Get the 4 adjacent cells (above, below, left and right).<br/>
* NOTE: a cell may be null in the list if it does not exist.
*/
public List<Cell> getAdjecentCells() {
List<Cell> result = new ArrayList<Cell>();
result.add(cellBlock(this.getX() + 1, this.getY()));
result.add(cellBlock(this.getX() - 1, this.getY()));
result.add(cellBlock(this.getX(), this.getY() + 1));
result.add(cellBlock(this.getX(), this.getY() - 1));
return result;
}
}

if/then with pixel finding and looping, all of which is above me at the moment

I want to take a screenshot, and if the pixel is the correct value RGB then take another screenshot and find next pixel or else repeat.
this is the code to get the pixel and it works like a charm!
{
BufferedImage image = robot.createScreenCapture(rectangle);
search: for(int x = 0; x < rectangle.getWidth(); x++)
{
for(int y = 0; y < rectangle.getHeight(); y++)
{
if(image.getRGB(x, y) == color3.getRGB())
{
break search;
}
}
}
}
what i want to know i guess is how would i go about asking it to repeat this segment of code until the pixel equals the true color. the color i am looking for is:
Color color3 = new Color(114, 46, 33);
Ok context, i am building a program that goes through steps, one opens the given puzzle, i have that down because i can use simple pixel data, then it needs to center the mouse on the center pixel. The problem is i cant just use a second get pixel image because it takes a while for the game to open the relevant jpanel so i need my program to wait until it can find a pixel indicating the game is open before it starts to look for the pixel to center the mouse.
You can probably separate the screenshot code into a method and call it until you get the desired result:
public boolean checkColor(Color inputColor) {
BufferedImage image = robot.createScreenCapture(rectangle);
for(int x = 0; x < rectangle.getWidth(); x++) {
for (int y = 0; y < rectangle.getHeight(); y++) {
if (image.getRGB(x, y) == inputColor.getRGB()) {
return true;
}
}
}
return false;
}
This method will return true if it can find the given inputColor in the screenshot. You might then use it in a loop as follows:
Color newColor = ...;
while (!checkColor(newColor)) {
new Color = new Color(114, 46, 33);
// Or change color in here for every iteration
}
This loop will terminate if it can't match the screenshot to newColor.

euclidean algorithm for image comparison

i am going to develop an application for image comparison on java. For this i have choosen euclidean algorithm. This application involves with 2 images.
1. Actual image
2. Part of the actual image.
Algorithm should compare the part of the image with actual image. If the part is existed in actual image, it should return one value as matching success.
Can anyone give me the algorithmic steps? code on java will be appreciated..!
Here is a relatively simple idea, with some parts left out intentionally, since the question smells like homework.
public static boolean contains(Image large, Image small) {
final int largeWidth = large.getWidth(), largeHeight = large.getHeight();
final int smallWidth = small.getWidth(), smallHeight = small.getHeight();
if (smallWidth > largeWidth || smallHeight > largeHeight) {
return false;
}
for (int x = 0; x < largeWidth - smallWidth; x++) {
for (int y = 0; y < largeHeight - smallHeight; y++) {
if (subImageEquals(large, x, y, small)) {
return true;
}
}
}
return false;
}
private static boolean subImageEquals(Image large, int x, int y, Image small) {
// TODO: checks whether all pixels starting at (x, y) match
// those of the small image.
}

Categories

Resources