2015-01-13 4 views
1

라이브러리없이 비트 맵에서 원을 감지하고 싶습니다. 첫째, 나는 2 진법을 위해 otsu thresold를 사용했다. 이진화 후 나는 라플라스 에지 검출을 사용했다. 이제 비트 맵에 원이 있습니다. 이 원을 어떻게 찾을 수 있습니까?서클 탐지없이 사용 Aforge 또는 OpenCv

참고 : 원을 그리고 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; 
     } 





    } 
} 

답변

0

이미지에 원이 몇 개인 경우 RANSAC을 사용하는 것이 좋습니다.

간략한 설명 : 가장자리 픽셀에서 임의로 3 점을 선택하고이 점에 맞는 find the equation of the circle을 선택하십시오. 남아있는 모든 모서리 점에서이 방정식을 사용하여 얼마나 많은 수가 방정식을 만족시키는 지 확인할 수 있습니다. 이 과정을 N 번 반복합니다 (N은 가장자리 수, 원의 수 등 다양한 요인에 따라 결정될 수 있음). 가장 높은 inliers 수 (원형에있는 점)로 반복을 기록하십시오. 이 최대 반복에 해당하는 방정식이 가장 적합한 서클입니다.

이미지에 둘 이상의 원이있는 경우 이전에 찾은 원에 맞는 모든 점을 삭제하거나 마스크 아웃 한 후 위 단계를 반복하십시오.

0

왜 Yonghong시에과 창족 지 "A NEW 효율적인 ELLIPSE 감지 방법"에 의해 쓰여진 종이를 살펴 필요가 없습니다. link

나는 타원형을 가지고 있지만 타원형이라는 것을 알고 있습니다.

힌트 : 당신의 procesing의 다음 단계는 클러스터링 당신의 가장자리 픽셀이어야합니다 - 픽셀이 객체를 만드는 당신이 알고있는 것입니다 이런 식으로. 우리는 객체가 속성 인을 가지고 있고 그 객체를 원으로 만드는 객체 속성을 결정한 다음 코드에서 이러한 속성 기반 필터를 구현해야합니다.