Обнаружение круга без использования Aforge или OpenCv

1

Я хочу обнаружить круги в растровом изображении без библиотеки. Во-первых, я использовал otsu thresold для бинаризации. После бинаризации я использовал обнаружение края лапласа. Теперь в моем растровом изображении есть круг. Как я могу определить этот круг.

ПРИМЕЧАНИЕ. Я попытался нарисовать круг и поплавать координатами x и y. Но этот путь настолько медленный, и этот путь имеет проблему радиуса. Потому что, если мой радиус tempCircle = 10 и действительный радиус круга = 9, то мой алгоритм не может найти круг.

    BitmapProcess bmpPro = new BitmapProcess((Bitmap)(pictureBox1.Image));
    bmpPro.LockBits();
    int black = 0, temp = 0,fixX=0,fixY=0;

    Bitmap bmp = (Bitmap)pictureBox1.Image;
    Graphics g = this.pictureBox1.CreateGraphics();
    Pen pen = new Pen(Color.Red, 10);
    int x = 0, y = 0;
    for (int a = 0; a < pictureBox1.Image.Width - 1; a += 1)
    {
        for (int b = 0; b < pictureBox1.Image.Height - 1; b++)
        {
            double radius = 10;

            temp = 0;
            for (double i = 0.0; i < 360.0; i += 1)
            {
                double angle = i * System.Math.PI / 180;
                x = (int)(a + radius * System.Math.Cos(angle));
                y = (int)(b + radius * System.Math.Sin(angle));
                Color aa = bmpPro.GetPixel(Math.Abs(x), Math.Abs(y));

                if (bmpPro.GetPixel(Math.Abs(x), Math.Abs(y))!=Color.Black) temp++;

            }
            if (temp > black)
            {
                black = temp;
                fixX = a;
                fixY = b;

            }

        }

    }
    g.DrawEllipse(pen,fixX,fixY,50,50);



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LockBitBitmap
{
    class BitmapProcess
    {
        public int b = 0;
        int TotalPixelLocked; 
        Bitmap source = null; //kaynak bmp
        IntPtr Iptr = IntPtr.Zero; //baslangıc adresi
        BitmapData bitmapData = null;

        public byte[] Pixels { get; set; }
        public int Depth { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }

        public BitmapProcess(Bitmap source)
        {
            this.source = source;  //bitmapı dısardan al
        }

        public void LockBits()
        {
            //resmin en ve boyunu al
            Width = source.Width;
            Height = source.Height;

            //kilit için rectangle olustur
            Rectangle rect = new Rectangle(0,0,Width,Height);

            //kaynak bitmap ın pixel formatını al
            Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);

            //pixel basına bit sayısını bul(Bpp)
            if (Depth != 8 && Depth != 24 && Depth != 32)
            {
                return; //bit türü desteklenmiyor...
            }

            //bitmapı kilitle ve veriyi döndür...          
            bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);

            //kilitlenecek pixel sayısını al
            TotalPixelLocked = Math.Abs(bitmapData.Stride) * source.Height;

            //pixel verilerini tutmak için byte dizisi olustur
            int step = Depth / 8;
            Pixels = new byte[TotalPixelLocked * step];
            Iptr = bitmapData.Scan0;

            //verileri pointerden diziye aktar
            Marshal.Copy(Iptr, Pixels, 0, TotalPixelLocked);

        }

        public Color GetPixel(int x, int y)
        {
            Color clr = Color.Empty; //boş renk

            //renkli nesne sayısını al
            int cCount = Depth / 8;

            //istenen pixelin baslangıc adresini bul
            int i = y * bitmapData.Stride + x * cCount;
            if (i > (Pixels.Length - cCount))
            {
                throw new IndexOutOfRangeException("index out of range ( dizi adresi geçersiz)");
            }
            if (Depth == 32) //r g b a
            {
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                byte a = Pixels[i + 3];
                clr = Color.FromArgb(a,r,g,b);
            }

            if (Depth == 24) //r g b 
            {
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                clr = Color.FromArgb(r, g, b);
            }

            if (Depth == 8) // r g b hepsi aynı
            {
                byte c = Pixels[i];
                clr = Color.FromArgb(c,c,c);
            }


            return clr;

        }

        public void SetPixel(int x, int y, Color color)
        {
            // renkli nesne sayısı
            int cCount = Depth / 8;

            // baslangıc indexini bul
            //int i = ((y * Width) + x) * cCount;
            int i = y * bitmapData.Stride + x * cCount;
            if (i > (Pixels.Length - cCount))
            {
                throw new IndexOutOfRangeException("index out of range ( dizi adresi geçersiz)");
            }
            if (Depth == 32) // r,g,b, (alpha)
            {
                Pixels[i] = color.B;
                Pixels[i + 1] = color.G;
                Pixels[i + 2] = color.R;
                Pixels[i + 3] = color.A;
            }
            if (Depth == 24) // r,g,b
            {
                Pixels[i] = color.B;
                Pixels[i + 1] = color.G;
                Pixels[i + 2] = color.R;
                b++;
            }
            if (Depth == 8)//r g b hepsi aynı
            {
                Pixels[i] = color.B;
            }
        }

        public Bitmap giveBitmap()
        {
            System.Runtime.InteropServices.Marshal.Copy(Pixels, 0, Iptr, TotalPixelLocked);
            source.UnlockBits(bitmapData);
            return source;
        }





    }
}
Теги:
opencv
image-processing
image
aforge

2 ответа

0
Лучший ответ

Если у вас есть только несколько кругов на изображении, я бы рекомендовал использовать RANSAC.

Краткое объяснение. Из ваших крайних пикселей выберите 3 точки в случайном порядке и найдите уравнение круга, которое соответствует этим точкам. Используйте это уравнение для всех оставшихся краевых точек, чтобы увидеть, сколько из них лежит на круге, то есть сколько удовлетворяют уравнению. Повторите этот процесс N раз (N можно определить на основе различных факторов, включая количество краевых точек, количество кругов и т.д.) И записать итерацию с наибольшим количеством линеек (точки, лежащие на круге). Уравнение, соответствующее этой максимальной итерации, является вашим наилучшим подходящим кругом.

Если на изображении имеется более одного круга, повторите описанные выше шаги после удаления или маскировки всех точек, которые были подобраны ранее найденными кругами.

0

Почему бы вам не взглянуть на статью, написанную Yonghong Xie и Qiang Ji "НОВЫЙ ЭФФЕКТИВНЫЙ МЕТОД ОБНАРУЖЕНИЯ ЭЛЛИПСА". ссылка

Я знаю, что у него есть эллипс в названии, но, поскольку вы наверняка знаете, что cricle - это просто особый эллипс;).

Подсказка. Следующий шаг в вашем процессе должен состоять в кластеризации ваших крайних пикселей - таким образом вы узнаете, какие пиксели создают объект. Поскольку мы знаем, что объекты имеют некоторые свойства, и вы должны определить, какие свойства объекта делают этот объект кругом, а затем реализовать эти фильтры на основе свойств в вашем коде.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню