三维霍夫空间转换

时间:2011-11-01 08:25:30

标签: c# image-processing computer-vision edge-detection hough-transform

我需要实现三维Hough空间,它可以检测圆的未知半径。我实施了2d霍夫空间。实际上我需要找到图像中圆圈的半径。你们可以指出我应该从哪里开始吗?

//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]++;
        }
    }


}
}

1 个答案:

答案 0 :(得分:2)

houghMap将变为houghMap = new short[height, width,radius];,并且每个半径将有一个循环。你必须为每个半径进行2d hough变换......