patternjavaMinor
Image-grouping using bit matrices
Viewed 0 times
bitimagegroupingusingmatrices
Problem
It might be easier to read the explanation of what I was trying to do, and implement it a completely different way, rather than go through the code. But the code does what I want it to do, just nowhere near any measurable efficiency.
This started off as an assignment that I got finished, but I know there has to be a decent amount of better ways to make this code work
The goal of this code is to take a matrices of 1's and 0's, and go through and any nodes (that are 1's) that are connected to the left, right, up, or down (no diagonals), to change to different numbers. Each group, the number goes up by one.
For example:
would become:
Here is my semi-verbal explanation of what the code does:
What my current code does, is works through this in 2 phases. First it goes through and finds the first 1, and changes it to 2, and changes every number to the left and right of that (assuming they are 1's) to 2's. And continues to work its way through.
After that, it goes through again, and finds every 2, and changes each number to the left, right, and down from that 2, to a 2 also (if it's not 0). And repeats that until it finds no more numbers connected to a 2. Then increments, and does that to 3's, and so on.
I know there has to be a simple way to do this recursively, and I've tried, but it's been a pretty big failure for me. Any help or insight would be greatly appreciated.
```
package imagegrouping;
public class ImageGrouping {
public static void main(String[] args) {
int [][] originalMap = new int[][]{
{1, 1, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 1, 1, 1},
{1, 0, 1, 0, 1, 1, 1},
{1, 1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0
This started off as an assignment that I got finished, but I know there has to be a decent amount of better ways to make this code work
The goal of this code is to take a matrices of 1's and 0's, and go through and any nodes (that are 1's) that are connected to the left, right, up, or down (no diagonals), to change to different numbers. Each group, the number goes up by one.
For example:
1 1 0 0 1 1 1
1 0 0 0 0 0 0
1 1 1 0 1 0 1
1 0 0 0 1 1 1
1 0 1 0 1 1 1
1 1 0 0 0 0 0
1 0 0 0 0 1 1would become:
2 2 0 0 3 3 3
2 0 0 0 0 0 0
2 2 2 0 4 0 4
2 0 0 0 4 4 4
2 0 5 0 4 4 4
2 2 0 0 0 0 0
2 0 0 0 0 6 6Here is my semi-verbal explanation of what the code does:
What my current code does, is works through this in 2 phases. First it goes through and finds the first 1, and changes it to 2, and changes every number to the left and right of that (assuming they are 1's) to 2's. And continues to work its way through.
After that, it goes through again, and finds every 2, and changes each number to the left, right, and down from that 2, to a 2 also (if it's not 0). And repeats that until it finds no more numbers connected to a 2. Then increments, and does that to 3's, and so on.
I know there has to be a simple way to do this recursively, and I've tried, but it's been a pretty big failure for me. Any help or insight would be greatly appreciated.
```
package imagegrouping;
public class ImageGrouping {
public static void main(String[] args) {
int [][] originalMap = new int[][]{
{1, 1, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 1, 1, 1},
{1, 0, 1, 0, 1, 1, 1},
{1, 1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0
Solution
I think your solution, and also the one proposed by Claudiordgz, are overkill.
You mentioned recursion in your question, and, recursion is the 'simple' solution to this problem.
problem description:
The goal of this code is to take a matrices of 1's and 0's, and go through and any nodes (that are 1's) that are connected to the left, right, up, or down (no diagonals), to change to different numbers. Each group, the number goes up by one
You can narrow this problem down in to four stages:
You do have a problem in your code that you have the 'magic-number' 7 embedded in your code. I have copied/pasted your code, and I have left the magic values in the
I have also split your main method in to different methods, so the logic is more discrete.
When you put it all together with a recursive method that 'handles' the out-of-bounds cases, it all looks pretty simple:
In the recursive method, note how it expects there to be invalid values. This is a recursive technique that makes it the responsibility of the recursion to check it's bounds. The alternative is to check the bounds each time before you call the next recursive level. By doing it the way I suggest you can reduce the amount of code you write, but at the small expense of recursing one level more than you need to.
The output from the above code, when I run it, is:
You mentioned recursion in your question, and, recursion is the 'simple' solution to this problem.
problem description:
The goal of this code is to take a matrices of 1's and 0's, and go through and any nodes (that are 1's) that are connected to the left, right, up, or down (no diagonals), to change to different numbers. Each group, the number goes up by one
You can narrow this problem down in to four stages:
- Set up a 'region counter', starting at 2
- Scan the matrix for a 1
- When you find a 1, recursively join it to all of it's 1-value neighbours, setting them all to the region-counter. You only need to look at 1-value'd neighbours.
- When you have completed the recursive join, increment the region-counter, and continue scanning for 1's.
You do have a problem in your code that you have the 'magic-number' 7 embedded in your code. I have copied/pasted your code, and I have left the magic values in the
printArray() method. Compare that with the other methods, and see how it can be done...I have also split your main method in to different methods, so the logic is more discrete.
When you put it all together with a recursive method that 'handles' the out-of-bounds cases, it all looks pretty simple:
public class ImageGrouping {
public static void main(String[] args) {
int[][] originalMap = new int[][] {
{ 1, 1, 0, 0, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 1, 1, 1 },
{ 1, 0, 1, 0, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 1, 1 } };
findGroups(originalMap);
printArray(originalMap);
}
public static final void findGroups(int[][] map) {
// step 1, set up the region count
int regioncount = 2;
// step 2, scan all cells of the map, looking for '1' values.
for (int row = 0; row = map.length) {
// illegal row.
return;
}
if (col = map[row].length) {
// illegal col.
return;
}
if (map[row][col] != 1) {
// only join 1-value cells.
return;
}
// set the group number.
map[row][col] = regioncount;
// check the neighbours...
joinGroup(map, row - 1, col, regioncount);
joinGroup(map, row + 1, col, regioncount);
joinGroup(map, row, col - 1, regioncount);
joinGroup(map, row, col + 1, regioncount);
}
// method to print array
public static void printArray(int[][] myArray) {
for (int x = 0; x < 7; x++) {
for (int y = 0; y < 7; y++) {
System.out.print(myArray[x][y]);
System.out.print(" ");
}
System.out.print("\n");
}
}
}In the recursive method, note how it expects there to be invalid values. This is a recursive technique that makes it the responsibility of the recursion to check it's bounds. The alternative is to check the bounds each time before you call the next recursive level. By doing it the way I suggest you can reduce the amount of code you write, but at the small expense of recursing one level more than you need to.
The output from the above code, when I run it, is:
2 2 0 0 3 3 3
2 0 0 0 0 0 0
2 2 2 0 4 0 4
2 0 0 0 4 4 4
2 0 5 0 4 4 4
2 2 0 0 0 0 0
2 0 0 0 0 6 6Code Snippets
public class ImageGrouping {
public static void main(String[] args) {
int[][] originalMap = new int[][] {
{ 1, 1, 0, 0, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 1, 1, 1 },
{ 1, 0, 1, 0, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 1, 1 } };
findGroups(originalMap);
printArray(originalMap);
}
public static final void findGroups(int[][] map) {
// step 1, set up the region count
int regioncount = 2;
// step 2, scan all cells of the map, looking for '1' values.
for (int row = 0; row < map.length; row++) {
for (int col = 0; col < map[row].length; col++) {
if (map[row][col] == 1) {
// step 3, recursively join 1-value cells.
joinGroup(map, row, col, regioncount);
// step 4, increment region count
regioncount++;
}
}
}
}
private static void joinGroup(int[][] map, int row, int col, int regioncount) {
// expect the recursive calls to generate invalid co-ordinates.
// ignore anything invalid.
if (row < 0 || row >= map.length) {
// illegal row.
return;
}
if (col < 0 || col >= map[row].length) {
// illegal col.
return;
}
if (map[row][col] != 1) {
// only join 1-value cells.
return;
}
// set the group number.
map[row][col] = regioncount;
// check the neighbours...
joinGroup(map, row - 1, col, regioncount);
joinGroup(map, row + 1, col, regioncount);
joinGroup(map, row, col - 1, regioncount);
joinGroup(map, row, col + 1, regioncount);
}
// method to print array
public static void printArray(int[][] myArray) {
for (int x = 0; x < 7; x++) {
for (int y = 0; y < 7; y++) {
System.out.print(myArray[x][y]);
System.out.print(" ");
}
System.out.print("\n");
}
}
}2 2 0 0 3 3 3
2 0 0 0 0 0 0
2 2 2 0 4 0 4
2 0 0 0 4 4 4
2 0 5 0 4 4 4
2 2 0 0 0 0 0
2 0 0 0 0 6 6Context
StackExchange Code Review Q#43987, answer score: 8
Revisions (0)
No revisions yet.