问题
I have this program to detect objects in a binarized BufferedImage, which the image is a multiple choice answer sheet.
I'm trying to use 4-Connectivity as in to detect each object (answer on the sheet).
So far what I have in hand as source is these:
- http://en.wikipedia.org/wiki/Connected-component_labeling
- http://homepages.inf.ed.ac.uk/rbf/HIPR2/label.htm
and I have came up with this, following instructions from Wikipedia:
if(getPixel(image, x, y) != 0){
if(getPixel(image, x-1, y) !=0){
System.out.println("we are in the same region");
region[x][y] = region[x-1][y];
}
else if(getPixel(image, x-1, y) !=0 && getPixel(image, x, y-1) !=0){
System.out.println("North and West pixels belong to the same region and must be merged");
region[x][y] = Math.min(region[x-1][y], region[x][y-1]);
}
else if( getPixel(image, x-1, y) ==0 && getPixel(image, x, y-1) !=0){
System.out.println("Assign the label of the North pixel to the current pixel");
region[x][y] = region[x][y-1];
}
else if(getPixel(image, x-1, y) ==0 && getPixel(image, x, y-1) ==0){
System.out.println("Create a new label id and assign it to the current pixel");
cpt++;
region[x][y] = cpt;
}
But the problem is it creates 51 regions! and it only prints a couple of top pixels of each object (not all pixels).
Can anyone please help me to find what the problem is and how can I detect my objects?
I would appreciate any help.
回答1:
You probably get a lot of regions because you do not seem to merge equal labels. There is no code for storing equal labels in your code snippet. The algorithm is a two-pass algorithm where the first pass assigns labels and the second pass merges equal labels.
Here are the condition checks quoted from the Wikipedia page:
Conditions to check:
- Does the pixel to the left (West) have the same value as the current pixel?
- Yes – We are in the same region. Assign the same label to the current pixel
- No – Check next condition
- Do both pixels to the North and West of the current pixel have the same value as the current pixel but not the same label?
- Yes – We know that the North and West pixels belong to the same region and must be merged. Assign the current pixel the minimum of the North and West labels, and record their equivalence relationship
- No – Check next condition
- Does the pixel to the left (West) have a different value and the one to the North the same value as the current pixel?
- Yes – Assign the label of the North pixel to the current pixel
- No – Check next condition
- Do the pixel's North and West neighbors have different pixel values than current pixel?
- Yes – Create a new label id and assign it to the current pixel
Your second condition check,
else if(getPixel(image, x-1, y) !=0 && getPixel(image, x, y-1) !=0)
does not check if the left pixel and up pixel have different labels.
Furthermore, just like supersam654 mentions in the comment, the first else if
will never be called. It seems like condition check (1) and (2) on the Wikipedia page should be in the opposite order. That is, first check if the left and up pixel have the same value as the current pixel but not the same label. Then, if that check fails, check if the left pixel has the same value as the current.
So try the following:
- Add the label condition to your second condition check.
- Switch the order of your first two condition checks.
- Keep track of equal labels (i.e., which labels represent the same region).
- Do a second pass over the image and merge equal labels.
I hope this helps.
回答2:
While I'm not entirely sure that this answers your question, I would modify your code to look like this:
if(getPixel(image, x, y) != 0){
if(getPixel(image, x-1, y) !=0){
if(getPixel(image, x, y-1) !=0) {
System.out.println("North and West pixels belong to the same region and must be merged");
region[x][y] = Math.min(region[x-1][y], region[x][y-1]);
} else {
System.out.println("we are in the same region");
region[x][y] = region[x-1][y];
}
} else if(getPixel(image, x-1, y) ==0) {
if(getPixel(image, x, y-1) !=0) {
System.out.println("Assign the label of the North pixel to the current pixel");
region[x][y] = region[x][y-1];
} else if (getPixel(image, x, y-1) ==0) {
System.out.println("Create a new label id and assign it to the current pixel");
cpt++;
region[x][y] = cpt;
}
}
来源:https://stackoverflow.com/questions/16419066/java-image-connective-component