我需要实现检测未知圆半径的三维霍夫空间。我实现了二维霍夫空间。实际上我需要找到图像中圆圈的半径。你们能指出我应该从哪里开始吗?
//Hough Circle Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
namespace imageipload
{
class HoughCirclez : IComparable
{
public readonly int X;
public readonly int Y;
public readonly int Radius;
public readonly short Intensity;
public readonly double RelativeIntensity;
public HoughCirclez(int x, int y, int radius, short intensity, double relativeIntensity)
{
X = x;
Y = y;
Radius = radius;
Intensity = intensity;
RelativeIntensity = relativeIntensity;
}
public int CompareTo(object value)
{
return (-Intensity.CompareTo(((HoughCirclez)value).Intensity));
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
namespace imageipload
{
class HoughCircleTrans
{
private int radiusToDetect;
private short[,] houghMap;
private short maxMapIntensity = 0;
// Hough map's width and height
private int width;
private int height;
private int localPeakRadius = 4;
private short minCircleIntensity = 10;
private ArrayList circles = new ArrayList();
public HoughCircleTrans(int radiusToDetect)
{
this.radiusToDetect = radiusToDetect;
}
public short MinCircleIntensity
{
get { return minCircleIntensity; }
set { minCircleIntensity = value; }
}
public int LocalPeakRadius
{
get { return localPeakRadius; }
set { localPeakRadius = Math.Max(1, Math.Min(10, value)); }
}
public short MaxIntensity
{
get { return maxMapIntensity; }
}
public int CirclesCount
{
get { return circles.Count; }
}
public void ProcessImage(Bitmap image)
{
// check image format
if (image.PixelFormat != PixelFormat.Format8bppIndexed)
throw new ArgumentException("Pixel format of source image should be 8 bpp indexed");
// lock source image
BitmapData imageData = image.LockBits(
new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
// process the image
ProcessImage(imageData);
// unlock image
image.UnlockBits(imageData);
}
public void ProcessImage(BitmapData imageData)
{
if (imageData.PixelFormat != PixelFormat.Format8bppIndexed)
throw new ArgumentException("Pixel format of source image should be 8 bpp indexed");
// get source image size
width = imageData.Width;
height = imageData.Height;
int srcOffset = imageData.Stride - width;
// allocate Hough map of the same size like image
houghMap = new short[height, width];
// do the job
unsafe
{
byte* src = (byte*)imageData.Scan0.ToPointer();
// for each row
for (int y = 0; y < height; y++)
{
// for each pixel
for (int x = 0; x < width; x++, src++)
{
if (*src != 0)
{
DrawHoughCircle(x, y);
}
}
src += srcOffset;
}
}
// find max value in Hough map
maxMapIntensity = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (houghMap[i, j] > maxMapIntensity)
{
maxMapIntensity = houghMap[i, j];
}
}
}
CollectCircles();
}
public Bitmap ToBitmap()
{
// check if Hough transformation was made already
if (houghMap == null)
{
throw new ApplicationException("Hough transformation was not done yet");
}
int width = houghMap.GetLength(1);
int height = houghMap.GetLength(0);
// create new image
Bitmap image = AForge.Imaging.Image.CreateGrayscaleImage(width, height);
// lock destination bitmap data
BitmapData imageData = image.LockBits(
new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
int offset = imageData.Stride - width;
float scale = 255.0f / maxMapIntensity;
// do the job
unsafe
{
byte* dst = (byte*)imageData.Scan0.ToPointer();
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++, dst++)
{
*dst = (byte)System.Math.Min(255, (int)(scale * houghMap[y, x]));
}
dst += offset;
}
}
// unlock destination images
image.UnlockBits(imageData);
return image;
}
public HoughCirclez[] GetMostIntensiveCircles(int count)
{
// lines count
int n = Math.Min(count, circles.Count);
if (n == 0)
return null;
// result array
HoughCirclez[] dst = new HoughCirclez[n];
circles.CopyTo(0, dst, 0, n);
return dst;
}
public HoughCirclez[] GetCirclesByRelativeIntensity(double minRelativeIntensity)
{
int count = 0, n = circles.Count;
while ((count < n) && (((HoughCirclez)circles[count]).RelativeIntensity >= minRelativeIntensity))
count++;
return GetMostIntensiveCircles(count);
}
private void CollectCircles()
{
short intensity;
bool foundGreater;
// clean circles collection
circles.Clear();
// for each Y coordinate
for (int y = 0; y < height; y++)
{
// for each X coordinate
for (int x = 0; x < width; x++)
{
// get current value
intensity = houghMap[y, x];
if (intensity < minCircleIntensity)
continue;
foundGreater = false;
// check neighboors
for (int ty = y - localPeakRadius, tyMax = y + localPeakRadius; ty < tyMax; ty++)
{
// continue if the coordinate is out of map
if (ty < 0)
continue;
// break if it is not local maximum or coordinate is out of map
if ((foundGreater == true) || (ty >= height))
break;
for (int tx = x - localPeakRadius, txMax = x + localPeakRadius; tx < txMax; tx++)
{
// continue or break if the coordinate is out of map
if (tx < 0)
continue;
if (tx >= width)
break;
// compare the neighboor with current value
if (houghMap[ty, tx] > intensity)
{
foundGreater = true;
break;
}
}
}
// was it local maximum ?
if (!foundGreater)
{
// we have local maximum
circles.Add(new HoughCirclez(x, y, radiusToDetect, intensity, (double)intensity / maxMapIntensity));
}
}
}
circles.Sort();
}
private void DrawHoughCircle(int xCenter, int yCenter)
{
int x = 0;
int y = radiusToDetect;
int p = (5 - radiusToDetect * 4) / 4;
SetHoughirclePoints(xCenter, yCenter, x, y);
while (x < y)
{
x++;
if (p < 0)
{
p += 2 * x + 1;
}
else
{
y--;
p += 2 * (x - y) + 1;
}
SetHoughirclePoints(xCenter, yCenter, x, y);
}
}
private void SetHoughirclePoints(int cx, int cy, int x, int y)
{
if (x == 0)
{
SetHoughPoint(cx, cy + y);
SetHoughPoint(cx, cy - y);
SetHoughPoint(cx + y, cy);
SetHoughPoint(cx - y, cy);
}
else if (x == y)
{
SetHoughPoint(cx + x, cy + y);
SetHoughPoint(cx - x, cy + y);
SetHoughPoint(cx + x, cy - y);
SetHoughPoint(cx - x, cy - y);
}
else if (x < y)
{
SetHoughPoint(cx + x, cy + y);
SetHoughPoint(cx - x, cy + y);
SetHoughPoint(cx + x, cy - y);
SetHoughPoint(cx - x, cy - y);
SetHoughPoint(cx + y, cy + x);
SetHoughPoint(cx - y, cy + x);
SetHoughPoint(cx + y, cy - x);
SetHoughPoint(cx - y, cy - x);
}
}
private void SetHoughPoint(int x, int y)
{
if ((x >= 0) && (y >= 0) && (x < width) && (y < height))
{
houghMap[y, x]++;
}
}
}
}