0

I wrote an application where some dots are floating around and if i assign a dot a Point, it will move on this position. Now i want to load an image, convert it to a monochrome image (Only pure black or white pixels - no shades of gray) and make each dot floating to a position where its representing a black pixel. I've already done loading and converting a image that way and extraceted the pixels as a 1 dimensional byte[]. I've managed to iterate though this array with the following code:

int stride = width * 4;
for (int y = 0; y < height; y++)
    for (int x = 0; x < width; x++)
    {
        int index = y * stride + 4 * x;
        // array[index] <- Red
        // array[index + 1] <- Green
        // array[index + 2] <- Blue
        // array[index + 3] <- Alpha
    }

The byte array holds every pixel with 4 bytes (RGBA). So the array length is ImageHeight*ImageWidth*4 bytes. Either a pixel is Black (0, 0, 0, 255) or White (255, 255, 255, 255).

My problem now is that i'm not able to correctly approximate the black areas of the image with just n dots. In most cases I will have much less floating dots than there are black pixels in the array. So what i need is a method that gives me a Point[] that contains n Points that will represent only the black areas of the image as good as possible. Can someone help me out?

Neralem
  • 101
  • 7
  • 2
    Possible duplicate of [What would be a good TRUE black and white colormatrix?](https://stackoverflow.com/questions/2746103/what-would-be-a-good-true-black-and-white-colormatrix) – Cee McSharpface Nov 11 '18 at 19:04

1 Answers1

0

Loop though the array and find the points that their red, green and blue are 0 to get the Black dots:

List<Point> blackPoints = new List<Points>()
for(int i=0; i<array.Length; i+=4)
    if(array[i] == 0 && array[i+1] == 0 && array[i+2] ==0) //alpha is not important
    {     
         int tmp = i / 4;
         blackPoints.Add(new Point(tmp%width, tmp/width));
    }

Create Methods, to get the weight of a pixel based on its own and neighbors colors, and also a Method to find the weight of a block:

public static class Exts
{
    public static int Weight(this points ps, int x, int y, int width, int height)
    {
         int weight = 0;
        for(int i=Math.Max(x - 1, 0); i<Math.Min(width, x+1))
            for(int j= Math.Max(y-1, 0), j<Math.Min(height, y+1))
                 if(ps.Any(a => a.X == i && a.Y == j)) weight++;
        return weight;
    }

    public static int BlockWeight(this Point[] ps, int x, int y)
    {
        return ps.Count(a => a.X <= x+2 && a.Y<= y+2);
    }   
}

Now loop through the bitmap, with blocks of nine pixels (3x3) and if a blocks wieght is more than half (in this case more than or equal to 5), select a the point in this block that has heighest weight, to represent the black point:

List<Point> result = new List<Point>();

for(int i=0; i<width; i+=3)
    for(int j=0; j< height; j+=3)
        if(points.BlockWeight(i,j) >= 5)
            result.Add(ps.Where(a => a.X <= x+2 && a.Y<= y+2).OrderByDescending(a => a.Weight(i, j, width, height)).First())
Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171
  • Yeah as i said i am able to iterate through the array but how do i get the coordinate of just n pixels that will describe the black areas as good as possible? Lets say the image is 300x300 pixels. 300*300 are 90,000 pixels. If there are 30,000 pixels black but i only have 3000 dots to represent them...which of these 30,000 black pixels should i chose to show the image with my dots? I cant just take every 10th cause this will create vertical strokes. I have to skip some rows and some columns...but i dont know how to do this :( – Neralem Nov 11 '18 at 19:28
  • that is image processing, you calculate a weight of dots (based on its neighbors (based on the number of its black dots) the dot which its weight is higher, would be the one. i will update my answer if you need help. do you? – Ashkan Mobayen Khiabani Nov 11 '18 at 19:34
  • This sounds very interesting :) Can you explain this a bit further? Thank you very much :) – Neralem Nov 11 '18 at 19:36
  • should it be 10, or can it be nine (3*3)? – Ashkan Mobayen Khiabani Nov 11 '18 at 19:39
  • What do you mean by 10? The ratio of blackPixels / n_dots? I hoped this wont matter...does it? – Neralem Nov 11 '18 at 19:41
  • this is something to discuss, you need at least 20 reps to be able to talk in chat – Ashkan Mobayen Khiabani Nov 11 '18 at 19:54
  • from my answer we have black dots, now you need a function that for a given dot, returns its weight based on its own color and the eight neighbors, then for example you loop throught image with 3*3 blocks (2 for loops with step equal to 3) any of these blocks of 3x3 that have 5 or more black dots (more than half) should contain a black dot, now where to put the black dot in these 9 pixels, in the one that has highest weight. – Ashkan Mobayen Khiabani Nov 11 '18 at 20:00
  • Wow that looks complicated^^ Thanks a lot for you efford but i'm not sure how to implement this correctly. I fixed some typos in you code (but i'm not sure if i did even this is correct). How can i set the number of dots i have? – Neralem Nov 11 '18 at 22:00
  • Seems that i've got a infinite loop in you last bit of code with the nested loop and the big linq expression which melts my brain :D But maybe my attempt to fix the compiler errors caused this... Can you maybe check it your self again? Thanks a lot! – Neralem Nov 11 '18 at 22:33