0

i have a problem regarding pixel analysis for an image.

I am trying to analyse every pixel that is white (R=255,G=255,B=255).

The problem is the storing/ reading of these data.

for (int i = 0; i <= Map.getHeight(); i++) {
            for (int j = 0; j <= Map.getWidth(); j++) {
                if (Map.getColor(j, i).getBlue() == 255 && Map.getColor(j, i).getRed() == 255
                        && Map.getColor(j, i).getGreen() == 255)
                {
//                  coordsX = new HashMap<>();
                    coordsX.put(j, new Rectangle(j, i, 5, 5));


                }

            }
            coordsY.put(i, coordsX);
        }
        System.out.println();
    }

The reading function is the following:

for (Entry<Integer, HashMap<Integer, Rectangle>> e : coordsY.entrySet()) {
            // HashMap<Integer, Rectangle> coordsX = coordsY.get(y);
            HashMap<Integer, Rectangle> coordsX = e.getValue();
            if (coordsX != null) {
                for (Entry<Integer, Rectangle> entry : coordsX.entrySet()) {
                    Rectangle rect = entry.getValue();
                    g.setColor(Color.red);
                    g.draw(rect);
                    if (this.car2.intersects(rect)) {
                        intersectsTrack = true;
                    }

                }
            }
        }

The problem is that when i outline:

coordsX = new HashMap<>();

like done above, i only get all one x value for one y value example.

If i dont outline this line it is the other way around. example.

Can you help me fixing this problem?

Kind Regards

complex
  • 13
  • 1
  • 2
  • 4

2 Answers2

2

You're creating a new coordsX everytime you've discovered a new white pixel. That's probably not what you intended. So for each y there will be one map coordsX with only one entry, any previous entry is discarded.

Also, I like to suggest to create a class for representing a 2D coordinate, let's call it Coordinate, then your algorithm gets much easier to implement. (or maybe there's already such a thing, for instance Point?)

class Coordinate {
    private int x, y;  // plus getter, setter, etc.

    public int hashCode() {
        return Objects.hash(x, y);
    }

    public boolean equals(Object obj) {
        if (obj == this)
            return true;
        else if (!(obj instanceof Coordinate))
            return false;

        Coordinate that = (Coordinate) obj;
        return this.x == that.x && this.y == that.y;
    }

    public String toString() {
        return "(" + x + ", " + y + ")";
    }
}

// ...

Map<Coordinate, Rectangle> coords = new HashMap<>();
for (int y = 0; y <= Map.getHeight(); y++) {
    for (int x = 0; x <= Map.getWidth(); x++) {
        Color color = Map.getColor(x, y);
        if (color.getBlue() == 255 && color.getRed() == 255 && color.getGreen() == 255) {
            Coordinate coordinate = new Coordinate(x, y);
            Rectangle rectangle = new Rectangle(x, y, 5, 5);
            coords.put(coordinate, rectangle);
        }
    }
}

for (Rectangle rectangle : coords.values()) {
    g.setColor(Color.red);
    g.draw(rect);
}
jabu.10245
  • 1,884
  • 1
  • 11
  • 20
  • Wow, thank you :) That works perfectly fine. Just created the Coordinates class and used your adjustments. I think i thought a bit too complicated at this stage. I really appreciate your help :) – complex Dec 04 '15 at 16:37
  • Dear jabu, i just tried to get only some rectangle entries (performance reasons) for the saved coordinates. But unfortunately it returns a 'null' instead of an rectangle every time. Even if i try to get all Rectangles for the coordinates. for (int y = 0; y <= Map.getHeight(); y++) { for (int x = 0; x <= Map.getWidth(); x++) { Coordinate coordinate = new Coordinate(x, y); Rectangle rectangle = coords.get(coordinate); g.draw(rectangle); } } is there something missing in my code? – complex Dec 05 '15 at 13:22
  • There are rectangles in my hash map I tested it. But u can't read the rectangle wir the for loop mentioned above – complex Dec 06 '15 at 21:26
  • Might be that your implementation of the `equals(Object)` and `hashCode()` in the `Coordinate` class is not correct. See [this answer](http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java/27609#27609) for more details. – jabu.10245 Dec 07 '15 at 10:01
  • thank you very much. i was not able to check but i forogt to implement the equals an hashcode builder in my code because i am not familiar with it. As i quick tested it it was working. Thank you again for your effort :). I will try your code later too. But as i noticed it looks much like my code which i just implemented – complex Dec 08 '15 at 16:52
0

What you're saying makes sense since your code coordsX.put(j, new Rectangle(j, i, 5, 5)); associates the x coordinate j with a Rectangle, while your code coordsY.put(i, coordsX); associates the final y coordinate i with the coordsX HashMap.

However, due to associating with only an x or y value, each put() call will overwrite if you put to the same coordinate, which you do with j i times. It might be better given your intention to have a single HashMap of an x/y pair class (such as a Point2D) that you map to a rectangle.

You can further optimize this by using some knowledge about a rectangle. If you want to store some x/y pairs for certain colors of an image, you can use a one Dimensional array, knowing you can index each coordinate as x + y * width, or in your case j + i * Map.getWidth(). I would design your array "hashmap" like so:

// put values in the array.
Rectangle[] coords = new Rectangle[Map.getWidth() * Map.getHeight()];
for (int i = 0; i <= Map.getHeight(); i++) {
    for (int j = 0; j <= Map.getWidth(); j++) {
        int index = j + i * map.getWidth();

        if (/* i,j has the correct color */) {
        coords[index] = new Rectangle(j, i, 5, 5);
        }
    }
}

// read values from the array
for (int i = 0; i <= Map.getHeight(); i++) {
    for (int j = 0; j <= Map.getWidth(); j++) {

        Rectangle rect = coords[j + i * Map.getWidth()];
        if(rect == null) continue;

        //Your read logic here
        g.setColor(Color.red);
        g.draw(rect);
        if (this.car2.intersects(rect)) {
            intersectsTrack = true;
        }
    }
}
aaroncarsonart
  • 1,054
  • 11
  • 27