java iterating through index +1 and -1 for image errosion model - java

I have been given the task of writing a script to "erode" a binary image i.e. black and white photo.
This means that I must distinguish the parts that are white from black, where on an RGB scale, black is 0 and 1 is white.
Pixels are iterated over on a horizontal (i index) and vertical (j index). In order for a pixel to be considered a particular colour, it's immediate neighbours must be of that colour i.e. i+1 and i-1 and j+1 and j-1.
My attempt to code this is as follows:
public static BufferedImage getErodedImage(BufferedImage image) {
BufferedImage target = copyImage(image);
for (int i = 0; i < image.getRaster().getWidth(); i++) {
for (int j = 0; j < image.getRaster().getHeight(); j++) {
if (i + 1)||(i - 1) == 0 {
i = 0
}
else{
i = 1
}
}
if (j + 1)||(j - 1) == 0 {
j = 0
}
else{
j = 1
}
}
}
My attempt is very pythonic and returns lots of Errors and I'm guessing that I might need another for loop to iterate the -1, 0 and +1 values. and then set the value of the i-th pixel.

In your code a lot of syntax error, try to use this code:
public static BufferedImage getErodedImage(BufferedImage image) {
BufferedImage target = copyImage(image);
for (int i = 0; i < image.getRaster().getWidth(); i++) {
for (int j = 0; j < image.getRaster().getHeight(); j++) {
if (i + 1 == 0 || i - 1 == 0) { // not if (i + 1)||(i - 1) == 0
i = 0; // ;
}
else{
i = 1; // ;
}
if (j + 1 == 0 ||j - 1 == 0) { // not if (j + 1)||(j - 1) == 0 and this "if" should be in "for (int j..."
j = 0; // ;
}
else{
j = 1; // ;
}
}
}
}

Related

matlab bwmorph(img, 'thin') implementation in Java gone wrong

I am implementing the matlab 'bwmorph(img, 'thin')' algorithm in Java ImageJ. I've searched all over the net pretty much and found some similar implementations that work better, but I can't find the issue in my code. Any ideas?
My code:
public void run(ImageProcessor ip) {
MakeBinary(ip);
int sum2 = processThin(ip);
int sum = -1;
while (sum2 != sum) {
sum = sum2;
sum2 = processThin(ip);
}
}
public int processThin(ImageProcessor ipOriginal) {
int sum = 0;
// first iteration
ImageProcessor ip = ipOriginal.duplicate();
for (int i = 1; i < ip.getWidth() -1; i++)
for (int j = 1; j < ip.getHeight() -1; j++) {
int[] neighbors = selectNeighbors(ip, i, j);
if (G1(neighbors) == 1 && G2(neighbors) >= 2 && G2(neighbors) <= 3 && G3(neighbors) == 0)
ip.putPixel(i,j, 0);
}
// second iteration
for (int i = 1; i < ip.getWidth() -1; i++)
for (int j = 1; j < ip.getHeight()-1; j++) {
int[] neighbors = selectNeighbors(ip, i, j);
if (G1(neighbors) == 1 && G2(neighbors) >= 2 && G2(neighbors) <= 3 && G3prime(neighbors) == 0)
ip.putPixel(i,j, 0);
}
for(int i = 0; i < ip.getWidth(); i++)
for(int j = 0; j < ip.getHeight(); j++) {
if (ip.getPixel(i,j) != 0) sum++;
ipOriginal.putPixel(i, j, ip.getPixel(i, j));
}
return sum;
}
private int G1(int[] input) {
int xh = 0;
for (int i = 1; i <= 4; i++) {
if (input[2 * i - 1] == 0 && (input[2 * i] == 1 || (2 * i + 1 <= 8 ? input[2 * i + 1] == 1 : input[1] == 1)))
xh += 1;
}
return xh;
}
private int G2(int[] input) {
int n1 = 0, n2 = 0;
n1 = toInt(toBool(input[4]) || toBool(input[3])) + toInt(toBool(input[1]) || toBool(input[2])) +
toInt(toBool(input[8]) || toBool(input[7])) + toInt(toBool(input[6]) || toBool(input[5]));
n2 = toInt(toBool(input[2]) || toBool(input[3])) + toInt(toBool(input[1]) || toBool(input[8])) +
toInt(toBool(input[6]) || toBool(input[7])) + toInt(toBool(input[4]) || toBool(input[5]));
return Math.min(n1,n2);
}
private int G3 (int[] input){
return toInt((toBool(input[2]) || toBool(input[3]) || !toBool(input[8])) && toBool(input[1]));
}
private int G3prime (int[] input){
return toInt((toBool(input[6]) || toBool(input[7]) || !toBool(input[4])) && toBool(input[5]));
}
private boolean toBool(int i ){
return i == 1;
}
private int toInt(boolean i) {
return i ? 1 : 0;
}
private int[] selectNeighbors(ImageProcessor ip, int i, int j) {
int[] result = new int[9];
result[1] = ip.getPixel(i+1,j);
result[2] = ip.getPixel(i+1,j+1);
result[3] = ip.getPixel(i,j+1);
result[4] = ip.getPixel(i-1,j+1);
result[5] = ip.getPixel(i-1,j);
result[6] = ip.getPixel(i-1,j-1);
result[7] = ip.getPixel(i,j-1);
result[8] = ip.getPixel(i+1,j-1);
for (int x = 0; x < result.length; x++)
if (result[x] != 0) result[x] = 1;
return result;
}
The main issue appears to be with the horizontal lines, but not only that.
Note: I've added the toBool and toInt methods to deal with convenient data types, the code was binary before and the result is the same apparently.
EDIT:
After editing the code and omitting doing modifications between two iterations, I ended up with this result now.
The code looks like this now.
public int processThin(ImageProcessor ip) {
int sum = 0;
// first iteration
int[][] mask = new int[ip.getWidth()][ip.getHeight()];
for (int i = 1; i < ip.getWidth() -1; i++)
for (int j = 1; j < ip.getHeight() -1; j++) {
int[] neighbors = selectNeighbors(ip, i, j);
if (G1(neighbors) == 1 && G2(neighbors) >= 2 && G2(neighbors) <= 3 && G3(neighbors) == 0)
mask[i][j]++;
}
// second iteration
for (int i = 1; i < ip.getWidth() -1; i++)
for (int j = 1; j < ip.getHeight()-1; j++) {
int[] neighbors = selectNeighbors(ip, i, j);
if (G1(neighbors) == 1 && G2(neighbors) >= 2 && G2(neighbors) <= 3 && G3prime(neighbors) == 0)
mask[i][j]++;
}
for(int i = 0; i < ip.getWidth(); i++)
for(int j = 0; j < ip.getHeight(); j++) {
if (mask[i][j] != 0) sum++;
ip.putPixel(i, j, mask[i][j] > 0 ? 0 : ip.getPixel(i,j));
}
return sum;
}
The problem in your original code is that you write into your input image. In the very first iteration, moving left to right, you remove successive pixels because each has, after modifying the previous pixel, a background pixel as neighbor.
There are different ways to implement the thinning operation, but the simplest one that works in-place like your code does requires two passes through the image for each iteration of the thinning:
Go through the image and mark all candidate pixels. These are the pixels that have a background neighbor. Marking a pixel can be as simple as setting the pixel value to a given constant, for example 42 (assuming background is 0 and foreground is 1 or 255 or whatever you decided on).
Go through the image again and for each marked pixel, determine if removing it would change the geometry of the foreground. If not, remove it. In this test, take the marked pixels that haven't been removed yet as foreground.

move to a new instance in an 2d array randomly once

so i a player on a 2d array, when i do an action i want the player to move to one of the 8 available blocks around him, the code below moves him randomly but does it twice
Map Before Moving
GrassGrassGrassGrass
Grass Rek GrassGrass
GrassGrassGrassGrass
GrassGrassGrassGrass
Random Movement
0 0
0 0 //This shouldn't be happening
Map After Moving
GrassGrassGrassGrass
GrassGrassGrassGrass
GrassGrassGrassGrass
GrassGrassGrass Rek
import java.util.Random;
public class command_Movment implements command_Move {
inSwamp map = new inSwamp();
inSwamp rek = new Rek();
Random random = new Random();
int row = random.nextInt(3);
int col = random.nextInt(3);
#Override
public Command move() {
for (int i = 0; i < map.grid.length; i++) {
for (int j = 0; j < map.grid[i].length; j++) {
if (map.grid[i][j] == rek.getName()) {
try {
map.grid[i][j] = "Grass";
if (row == 0) {
i++;
}
if (row == 1) {
i--;
}
if (col == 0) {
j++;
}
if (col == 1) {
j--;
}
map.grid[i][j] = rek.getName();
System.out.println(col + " " + row);
break;
} catch (ArrayIndexOutOfBoundsException exception) {
if (row == 0) {
i--;
}
if (row == 1) {
i++;
}
if (col == 0) {
j--;
}
if (col == 1) {
j++;
}
map.grid[i][j] = rek.getName();
System.out.println("Error");
break;
}
}
}
}
return null;
}
}
Firstly, you shouldn't use == to compare strings, you should use equals method. so replace if (map.grid[i][j] == rek.getName()) with if (map.grid[i][j].equals(rek.getName())).
Edit: PLEASE don't use label to break the modularity of the program!
Please don't use catching ArrayIndexOutofBound exception to determine if an array index is correct or not. The exception should NOT happen. You should check the index first.
I updated my program for your random move: basically I thin you want to:
1) randomly move up or move down from the original position 2) if move up or move down exceeds the boundary of the matrix, don't move in that direction.
The following program should move rek to one of its 8 neighbors randomly without causing any ArrayIndexOutOfBoundException.
public Command move() {
// randomly determine the moving direction
// -1 means move left, 1 means move right
int horizontal_direction = Math.random() > 0.5 ? -1 : 1;
// -1 means move up, 1 mean move down
int vertical_direction = Math.random() > 0.5 ? -1 : 1;
for (int i = 0; i < map.grid.length; i++) {
for (int j = 0; j < map.grid[i].length; j++) {
if (map.grid[i][j].equals(rek.getName())) {
map.grid[i][j] = "Grass"; // replace rek's current position with Grass\
// if the newRow exceeds the boundaries, don't move in that direction
int newRow = i + horizontal_direction;
if (newRow < 0 || newRow == map.grid.length)
newRow = i;
// if the newCol exceeds the boundaries, don't move in that direction
int newCol = j + vertical_direction;
if (newCol < 0 || newCol == map.grid[i].length)
newCol = j;
map.grid[newRow][newCol] = rek.getName(); // move rek to the new position
System.out.println(newRow + " " + newCol);
break;
}
}
}
return null;
}
Add a label like this to your outer loop:
outer:
for (int i = 0; i < map.grid.length; i++) {
......
}
And in the try block, break the loop this way:
map.grid[i][j] = rek.getName();
System.out.println(col + " " + row);
break outer;

Is there a way to combine incrementing and decrementing for loops?

int j = 0;
for (int i = 1; i < 4; i++)
{
if ((columnIndex + i) > 6 || this.isWinningCondition(columnIndex, i, j, colSlot, isRed))
{
break;
}
else
{
pieces++;
}
}
for (int i = -1; i > -4; i--)
{
if ((columnIndex + i) < 0 || this.isWinningCondition(columnIndex, i, j, colSlot, isRed))
{
break;
}
else
{
pieces++;
}
}
Basically, it is apart of a Connect4 program that searches for three in a row on the left and right side of a specific column (in this case, it is searching for horizontal wins), hence the incrementing (for the right side) and the decrementing (for the left side) for loops. Is there a way I can combine these for loops into one, so I don't have to repeat myself?
If your MaxValue ( 4 )is always the same for both for loop, you can always do :
for( int i = 1; i < 4; ++i)
{
//verify i version 1
int i2 = i * -1;
// verify i2 version 2
}
Try the mixed for loop.
for(int i = 0, j = 4; i <= 4 && j >=0; i ++, j --)
{
System.out.println(i + " " + j);
}
Output:
0 4
1 3
2 2
3 1
4 0

How to print out an X using nested loops

I have searched through to find a simple solution to this problem.
I have a method called
printCross(int size,char display)
It accepts a size and prints an X with the char variable it receives of height and width of size.
The calling method printShape(int maxSize, char display) accepts the maximum size of the shape and goes in a loop, sending multiples of 2 to the printCross method until it gets to the maximum.
Here is my code but it is not giving me the desired outcome.
public static void drawShape(char display, int maxSize)
{
int currentSize = 2; //start at 2 and increase in multiples of 2 till maxSize
while(currentSize<=maxSize)
{
printCross(currentSize,display);
currentSize = currentSize + 2;//increment by multiples of 2
}
}
public static void printCross(int size, char display)
{
for (int row = 0; row<size; row++)
{
for (int col=0; col<size; col++)
{
if (row == col)
System.out.print(display);
if (row == 1 && col == 5)
System.out.print(display);
if (row == 2 && col == 4)
System.out.print(display);
if ( row == 4 && col == 2)
System.out.print(display);
if (row == 5 && col == 1)
System.out.print(display);
else
System.out.print(" ");
}
System.out.println();
}
}
Is it because I hardcoded the figures into the loop? I did a lot of math but unfortunately it's only this way that I have been slightly close to achieving my desired output.
If the printCross() method received a size of 5 for instance, the output should be like this:
x x
x x
x
x x
x x
Please I have spent weeks on this and seem to be going nowhere. Thanks
The first thing you have to do is to find relationships between indices. Let's say you have the square matrix of length size (size = 5 in the example):
0 1 2 3 4
0 x x
1 x x
2 x
3 x x
4 x x
What you can notice is that in the diagonal from (0,0) to (4,4), indices are the same (in the code this means row == col).
Also, you can notice that in the diagonal from (0,4) to (4,0) indices always sum up to 4, which is size - 1 (in the code this is row + col == size - 1).
So in the code, you will loop through rows and then through columns (nested loop). On each iteration you have to check if the conditions mentioned above are met. The logical OR (||) operator is used to avoid using two if statements.
Code:
public static void printCross(int size, char display)
{
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
if (row == col || row + col == size - 1) {
System.out.print(display);
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
Output: (size = 5, display = 'x')
x x
x x
x
x x
x x
Instead of giving a direct answer, I will give you some hints.
First, you are right to use nested for loops.
However as you noticed, you determine when to print 'x' for the case of 5.
Check that 'x' is printed if and only if row = col or row + col = size - 1
for your printCross method, try this:
public static void printCross(int size, char display) {
if( size <= 0 ) {
return;
}
for( int row = 0; row < size; row++ ) {
for( int col = 0; col < size; col++ ) {
if( col == row || col == size - row - 1) {
System.out.print(display);
}
else {
System.out.print(" ");
}
}
System.out.println();
}
}
ah, I got beaten to it xD
Here's a short, ugly solution which doesn't use any whitespace strings or nested looping.
public static void printCross(int size, char display) {
for (int i = 1, j = size; i <= size && j > 0; i++, j--) {
System.out.printf(
i < j ? "%" + i + "s" + "%" + (j - i) + "s%n"
: i > j ? "%" + j + "s" + "%" + (i - j) + "s%n"
: "%" + i + "s%n", //intersection
display, display
);
}
}
Lte's try this simple code to print cross pattern.
class CrossPattern {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("enter the number of rows=column");
int n = s.nextInt();
int i, j;
s.close();
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
if (j == i) {
System.out.print("*");
} else if (j == n - (i - 1)) {
System.out.print("*");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}

Java 2D Array manipulation

I have to modify the below method:
private final static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
}
This method checks if it's a even number and if so it replaces its value with 0. Simple.
I now need to modify it so that it directs each cell to simultaneously replace its value with its number of diagonal neighbors that hold a value of 0.
I've thought about this for about an hour and tried many different solutions, most of which resulted in an out of bounds exception. I'm stumped and don't know how to accomplish this.
If the code is right, using the integers for the grid array below, it will reproduce the numbers shown in the bottom of the picture.
What is the problem, you just need to put if statements, like there can be maximum 4 possible neighbors so check that how many are equal to 0. But this is not enough you just need to add one more condition in each of the if statements. The condition would be that the neighbor you are trying to check is possible or not.
That is: Total 4 neighbors. If the coordinates of your main cell are x, y then:
1st Diagonal neighbor: x-1, y-1
2nd Diagonal neighbor: x-1, y+1
3rd Diagonal neighbor: x+1, y+1
4th Diagonal neighbor: x+1, y-1
These are all the 4 diagonal neighbors' coordinates but the last thing you need to check is whether they go out of bonds or not. For example for checking the 1st Diagonal neighbor I would do:
if((x-1)>0 && (y-1)>0){
//and then check here if that block is = `0`
}
and for other having say x+1 or y+1 you will need to check whether or not they are less than the NUM. Like if I want to check the 3rd Diagonal Neighbor:
if((x+1)<NUM && (y+1)<NUM){
//and then check here if that block is = `0`
}
Update: What do you mean by check here if that block is = 0?
If you want to check that is the diagonal neighboring blocks are equal to 0 or not then you will need to do it in a loop. Here is how:
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
for(row = 0; row< NUM; row++){
for(int col = 0; col < NUM; col++) {
int count = 0;
// To check for the 1st Diagonal Neighbor
if((row-1)>0 && (col-1)>0){
if(grid[row-1][col-1]==0){
count++;
}
}
//Similarly for 2nd, 3rd and 4th Diagonal Neighbors
//and then
grid[row][col]=count;
}
}
}
Update 2:
For say the 3rd diagonal neighbor the code block would be like this:
if((row+1)<NUM && (col+1)<NUM){
if(grid[row+1][col+1]==0){
count++;
}
}
Answer
final private static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
int counter = 0;
if((row - 1) > 0 && (col - 1) > 0) {
if(grid[row - 1][col - 1] == 0) {
counter++;
}
}
if((row - 1) > 0 && (col + 1) < NUM) {
if(grid[row - 1][col + 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col - 1) > 0) {
if(grid[row + 1][col - 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col + 1) < NUM) {
if(grid[row + 1][col + 1] == 0) {
counter++;
}
}
grid[row][col] = counter;
}
}
}

Categories