I have x, y coordinates of all vertices of a polygon, say (1,1) (20,10) (10,30), how do I generate a mask with all pixels inside the polygon being 1 whereas outside being 0?
I know there is a function FillPolygon()
in C# that looks pretty much doing the job, but it seems to me that it does not return a mask in any way.
Asked
Active
Viewed 1,383 times
1

Nick Tsui
- 524
- 2
- 9
- 29
-
1what is a mask by your standards? what data do you want to get back? – Rotem Jan 16 '13 at 15:33
3 Answers
1
Bitmap b = new Bitmap(30, 30);
using (Graphics g = Graphics.FromImage(b))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.Clear(Color.Black);
g.FillPolygon(Brushes.White, new Point[] {
new Point(5,5),
new Point(20,20),
new Point(2,15)});
}
byte[,] mask = new byte[b.Width, b.Height];
for (int y = 0; y < b.Height; y++)
for (int x = 0; x < b.Width; x++)
{
mask[x, y] = b.GetPixel(x, y).R > 0 ? 1 : 0;
}
This will of course be more performant if you use direct pixel access using LockBits
instead of GetPixel
.

Rotem
- 21,452
- 6
- 62
- 109
-
Can I using something else instead of Bitmap and Graphics? Because these requires adding System.Drawing, which conflicts with my Point class that is already in the project. – Nick Tsui Jan 17 '13 at 00:53
-
@NickTsui If you want to use `FillPolygon`, I don't see any other way. Otherwise you need to roll your own polygon filling function. There are ways getting arround class name conflicts, like aliasing. – Rotem Jan 17 '13 at 06:59
1
I know this is rather old question but in case someone comes around and looks for something similar ...
If you just want to get the mask, there are much better approaches than referencing System.Drawing and actually drawing onto image in memory ...
struct Point
{
public readonly int X;
public readonly int Y;
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
}
bool PointInPolygon(Point[] polygon, int x, int y)
{
if(polygon == null || polygon.Length < 3) return false;
int counter = 0;
double intersections;
Point p1 = polygon[0];
Point p2;
for (int i = 1; i <= polygon.Length; i++)
{
p2 = polygon[i % polygon.Length];
if ((y > (p1.Y < p2.Y ? p1.Y : p2.Y)) && (y <= (p1.Y > p2.Y ? p1.Y : p2.Y)) && (x <= (p1.X > p2.X ? p1.X : p2.X)) && (p1.Y != p2.Y))
{
intersections = (y - p1.Y) * (p2.X - p1.X) / (p2.Y - p1.Y) + p1.X;
if (p1.X == p2.X || x <= intersections) counter++;
}
p1 = p2;
}
return counter % 2 != 0;
}
void Main()
{
Point[] polygon = new Point[] { new Point(1,1), new Point(20,10), new Point(10,30) };
bool[,] mask = new bool[30,30];
for(int i=0;i<30;i++)
{
for(int j=0;j<30;j++)
{
mask[i,j] = PointInPolygon(polygon, i, j);
Console.Write(mask[i,j]?"*":".");
}
Console.WriteLine();
}
}
Which will output like this:
..............................
..............................
..............................
..***.........................
...*****......................
...********...................
....**********................
....**************............
.....****************.........
.....*******************......
......*********************...
......************************
.......*********************..
.......*******************....
........****************......
........**************........
.........***********..........
.........*********............
..........******..............
..........****................
..........**..................
..............................
..............................
..............................
..............................
..............................
..............................
..............................
..............................
..............................

Juraj Maciak
- 11
- 1
- 2
0
For playng with masking, you can use a Region.

Felice Pollano
- 32,832
- 9
- 75
- 115
-
Say I have a 10 by 10 image, with each axis starting from 1 to 10; Then I have a 3 dots (2,2) (8 3) (5 7) defining a triangle, what I want to have is a matrix with all elements inside the triangle being 1 and outside being 0; – Nick Tsui Jan 16 '13 at 16:18