Counting Regions in Images II
Carrying on from the previous post, in order to better illustrate the affects of the different thresholds, the thresholds were made as input parameters to this new algorithm, and in addition the color of each region was made different from each other, plus some bug fixes (casting fixes, etc.).
To illustrate the concept I picked up an image of me running and applied the algorithm varying the thresholds. As you can see from the image below, the smaller the thresholds the more regions it finds, and conversely as we increase the thresholds the bigger and the fewer the regions are.
If one makes the thresholds zero, it will imply that each pixel will be its own region. Similarly, when the threshold goes to infinity, the entire image becomes just one big region. Hope this helps - cheers, Marcelo.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Collections;
namespace CountRegions
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 3)
{
Console.WriteLine("Usage: CountRegions.exe <image file> <neighbors threshold> <center threshold>");
return;
}
MyImage myImage = new MyImage(args[0], Int32.Parse(args[1]), Int32.Parse(args[2]));
Console.WriteLine("Processing...");
myImage.CountRegions();
Console.WriteLine("Done!");
}
}
class MyImage
{
Bitmap image = null;
int thresholdNeighbor = 50; //Some default...
int thresholdSeed = 60; //Some default...
private MyImage() { }
public MyImage(string imageFileName, int thresholdNeighbor, int thresholdSeed)
{
this.image = new Bitmap(imageFileName);
this.thresholdNeighbor = thresholdNeighbor;
this.thresholdSeed = thresholdSeed;
}
public void CountRegions()
{
bool[,] mark = new bool[image.Width, image.Height];
Color[] regionColors = {
Color.DarkBlue,
Color.DarkCyan,
Color.DarkGoldenrod,
Color.DarkGray,
Color.DarkGreen,
Color.DarkKhaki,
Color.DarkMagenta,
Color.DarkOliveGreen,
Color.DarkOrange,
Color.DarkOrchid,
Color.DarkRed,
Color.DarkSalmon,
Color.DarkSeaGreen,
Color.DarkSlateBlue,
Color.DarkSlateGray,
Color.DarkTurquoise,
Color.DarkViolet
};
int indexRegionColors = 0;
for (int c = 0; c < image.Width; c++)
{
for (int r = 0; r < image.Height; r++)
{
Color color = image.GetPixel(c, r);
if (!(color.R == 255 && color.G == 255 && color.B == 255))
{
if (!mark[c, r])
{
RegionMarkdownBFS(c, r, thresholdNeighbor, thresholdSeed, mark, regionColors[indexRegionColors]);
indexRegionColors = (indexRegionColors + 1) % regionColors.Length;
}
}
}
}
Random rd = new Random();
string outputFileName = "output_" + rd.Next().ToString() + ".jpg";
image.Save(outputFileName);
Console.WriteLine("File saved to {0}", outputFileName);
}
private void RegionMarkdownBFS(int c, int r, int thresholdNeighbor, int thresholdSeed, bool[,] mark, Color regionColor)
{
Queue queue = new Queue();
Color pixelSeed = image.GetPixel(c, r);
mark[c, r] = true;
image.SetPixel(c, r, regionColor);
long key = r * image.Width + c;
queue.Enqueue(key);
while (queue.Count > 0)
{
key = (long)queue.Dequeue();
int currentRow = (int)(key / image.Width);
int currentCol = (int)(key % image.Width);
Color currentColor = image.GetPixel(currentCol, currentRow);
//Mark in the image
image.SetPixel(currentCol, currentRow, regionColor);
//Check neighbors
for (int or = -1; or <= 1; or++)
{
for (int oc = -1; oc <= 1; oc++)
{
if (currentRow + or >= 0 &&
currentRow + or < image.Height &&
currentCol + oc >= 0 &&
currentCol + oc < image.Width &&
!mark[currentCol + oc, currentRow + or])
{
Color neighborColor = image.GetPixel(currentCol + oc, currentRow + or);
if (!(neighborColor.R == 255 && neighborColor.G == 255 && neighborColor.B == 255))
{
if (Math.Abs(neighborColor.R - currentColor.R) <= thresholdNeighbor &&
Math.Abs(neighborColor.G - currentColor.G) <= thresholdNeighbor &&
Math.Abs(neighborColor.B - currentColor.B) <= thresholdNeighbor)
{
if (Math.Abs(neighborColor.R - pixelSeed.R) <= thresholdSeed &&
Math.Abs(neighborColor.G - pixelSeed.G) <= thresholdSeed &&
Math.Abs(neighborColor.B - pixelSeed.B) <= thresholdSeed)
{
queue.Enqueue((long)(currentRow + or) * image.Width + currentCol + oc);
mark[currentCol + oc, currentRow + or] = true;
}
}
}
}
}
}
}
}
public void Print()
{
for (int r = 0; r < image.Height; r++)
{
for (int c = 0; c < image.Width; c++)
{
Color color = image.GetPixel(c, r);
Console.Write("({0},{1},{2}) ", color.R, color.G, color.B);
}
Console.WriteLine();
}
}
}
}
To illustrate the concept I picked up an image of me running and applied the algorithm varying the thresholds. As you can see from the image below, the smaller the thresholds the more regions it finds, and conversely as we increase the thresholds the bigger and the fewer the regions are.
If one makes the thresholds zero, it will imply that each pixel will be its own region. Similarly, when the threshold goes to infinity, the entire image becomes just one big region. Hope this helps - cheers, Marcelo.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Collections;
namespace CountRegions
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 3)
{
Console.WriteLine("Usage: CountRegions.exe <image file> <neighbors threshold> <center threshold>");
return;
}
MyImage myImage = new MyImage(args[0], Int32.Parse(args[1]), Int32.Parse(args[2]));
Console.WriteLine("Processing...");
myImage.CountRegions();
Console.WriteLine("Done!");
}
}
class MyImage
{
Bitmap image = null;
int thresholdNeighbor = 50; //Some default...
int thresholdSeed = 60; //Some default...
private MyImage() { }
public MyImage(string imageFileName, int thresholdNeighbor, int thresholdSeed)
{
this.image = new Bitmap(imageFileName);
this.thresholdNeighbor = thresholdNeighbor;
this.thresholdSeed = thresholdSeed;
}
public void CountRegions()
{
bool[,] mark = new bool[image.Width, image.Height];
Color[] regionColors = {
Color.DarkBlue,
Color.DarkCyan,
Color.DarkGoldenrod,
Color.DarkGray,
Color.DarkGreen,
Color.DarkKhaki,
Color.DarkMagenta,
Color.DarkOliveGreen,
Color.DarkOrange,
Color.DarkOrchid,
Color.DarkRed,
Color.DarkSalmon,
Color.DarkSeaGreen,
Color.DarkSlateBlue,
Color.DarkSlateGray,
Color.DarkTurquoise,
Color.DarkViolet
};
int indexRegionColors = 0;
for (int c = 0; c < image.Width; c++)
{
for (int r = 0; r < image.Height; r++)
{
Color color = image.GetPixel(c, r);
if (!(color.R == 255 && color.G == 255 && color.B == 255))
{
if (!mark[c, r])
{
RegionMarkdownBFS(c, r, thresholdNeighbor, thresholdSeed, mark, regionColors[indexRegionColors]);
indexRegionColors = (indexRegionColors + 1) % regionColors.Length;
}
}
}
}
Random rd = new Random();
string outputFileName = "output_" + rd.Next().ToString() + ".jpg";
image.Save(outputFileName);
Console.WriteLine("File saved to {0}", outputFileName);
}
private void RegionMarkdownBFS(int c, int r, int thresholdNeighbor, int thresholdSeed, bool[,] mark, Color regionColor)
{
Queue queue = new Queue();
Color pixelSeed = image.GetPixel(c, r);
mark[c, r] = true;
image.SetPixel(c, r, regionColor);
long key = r * image.Width + c;
queue.Enqueue(key);
while (queue.Count > 0)
{
key = (long)queue.Dequeue();
int currentRow = (int)(key / image.Width);
int currentCol = (int)(key % image.Width);
Color currentColor = image.GetPixel(currentCol, currentRow);
//Mark in the image
image.SetPixel(currentCol, currentRow, regionColor);
//Check neighbors
for (int or = -1; or <= 1; or++)
{
for (int oc = -1; oc <= 1; oc++)
{
if (currentRow + or >= 0 &&
currentRow + or < image.Height &&
currentCol + oc >= 0 &&
currentCol + oc < image.Width &&
!mark[currentCol + oc, currentRow + or])
{
Color neighborColor = image.GetPixel(currentCol + oc, currentRow + or);
if (!(neighborColor.R == 255 && neighborColor.G == 255 && neighborColor.B == 255))
{
if (Math.Abs(neighborColor.R - currentColor.R) <= thresholdNeighbor &&
Math.Abs(neighborColor.G - currentColor.G) <= thresholdNeighbor &&
Math.Abs(neighborColor.B - currentColor.B) <= thresholdNeighbor)
{
if (Math.Abs(neighborColor.R - pixelSeed.R) <= thresholdSeed &&
Math.Abs(neighborColor.G - pixelSeed.G) <= thresholdSeed &&
Math.Abs(neighborColor.B - pixelSeed.B) <= thresholdSeed)
{
queue.Enqueue((long)(currentRow + or) * image.Width + currentCol + oc);
mark[currentCol + oc, currentRow + or] = true;
}
}
}
}
}
}
}
}
public void Print()
{
for (int r = 0; r < image.Height; r++)
{
for (int c = 0; c < image.Width; c++)
{
Color color = image.GetPixel(c, r);
Console.Write("({0},{1},{2}) ", color.R, color.G, color.B);
}
Console.WriteLine();
}
}
}
}
Comments
Post a Comment