Rss Feed

C# ile Görüntü İşleme – 1

Tarih: November 23rd, 2008 | Yazan: | Kategori: Programlama | Etiketler: , , | 29 Yorum »

Blogda bu kadar kod dolu yazılar yazmak konusunda kararszıdım ama yine de bir kez denemek istedim bakalım ilgi olacak mı.

Görüntü işleme ile ilgili temel bilgileri biliyorsunuz farzederek bu yazıyı yazıyorum. Zira işin hikaye kısmını yazması biraz zor oluyor diyerekten konuya geçelim.

Görüntü işleme sırasında image veya bitmap nesneleri üzerinde işlem yapmak yerine dizileri kullanıyorum ondan dolayı aşağıdaki kodlarda da bütün işlemler diziler üzerinde olacak. Kullandığım birçok fonksiyon pointer kullanarak çalışıyor. C# ile nasıl pointer kullanacağınızı bilmiyorsanız şurada bulunan yazımı okuyabilirsiniz.

Öncelikle picturebox nesnesinden diziye dönüşüm işlemini yapan fonksiyonu verelim:


int[,] pixelArray = new int[pictureBox1.Image.Height, pictureBox1.Image.Width];
int[,] greyPixelArray = new int[pictureBox1.Image.Height, pictureBox1.Image.Width];

private void BuildPixelArray(Image myImage)
{
Rectangle rect = new Rectangle(0, 0, myImage.Width, myImage.Height);
Bitmap temp = new Bitmap(myImage);
BitmapData bmpData = temp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int remain = bmpData.Stride - bmpData.Width * 3;
unsafe
{
byte* ptr = (byte*)bmpData.Scan0;
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
pixelArray[i, j] = ptr[0] + ptr[1] * 255 + ptr[2] * 255 * 255;
greyPixelArray[i, j] = (int)((double)ptr[0] * 0.11 + (double)ptr[1] * 0.59 + (double)ptr[2] * 0.3);
ptr += 3;
}
ptr += remain;
}
}
temp.UnlockBits(bmpData);
}

Bu fonksiyon sayesinde picturebox nesnesindeki görüntüyü pixelArray dizisine taşıyoruz. Aynı fonksiyonda greyPixelArray dizisi ile tutulan griseviye görüntü de oluşturuluyor.

Dizideki görüntüyü form üzerinde bulunan bir picturebox nesnesine aktarmak için aşağıdaki fonksiyonu kullanabilirsiniz.


private void SetImage(int[,] sourceArray, ref PictureBox myPictureBox)
{
Rectangle rect = new Rectangle(0, 0, myPictureBox.Image.Width, myPictureBox.Image.Height);
Bitmap temp = new Bitmap(myPictureBox.Image);
BitmapData bmpData = temp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int remain = bmpData.Stride - bmpData.Width * 3;
unsafe
{
byte* ptr = (byte*)bmpData.Scan0;
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
ptr[0] = ptr[1] = ptr[2] = (byte)sourceArray[i, j];
ptr += 3;
}
ptr += remain;
}
}
temp.UnlockBits(bmpData);
myPictureBox.Image = temp;
}

Üstteki fonksiyon aldığı diziyi gri seviye olarak değerlendiriyor. Eğer renkli bir görüntünüz varsa bir aşağıdaki fonksiyonu kullanabilirsiniz


public void SetColorImage(ref int[,] sourceArray)
{
Rectangle rect = new Rectangle(0, 0, sourceArray.GetLength(0), sourceArray.GetLength(1));
Bitmap temp = new Bitmap(sourceArray.GetLength(0), sourceArray.GetLength(1));
BitmapData bmpData = temp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int remain = bmpData.Stride - bmpData.Width * 3;
unsafe
{
byte* ptr = (byte*)bmpData.Scan0;
for (int i = 0; i < bmpData.Width; i++)
{
for (int j = 0; j < bmpData.Height; j++)
{
ptr[0] = (byte)(sourceArray[i, j]%256);
ptr[1] = (byte)((sourceArray[i, j]/256)%256);
ptr[2] = (byte)((sourceArray[i, j]/65536)%256);
ptr += 3;
}
ptr += remain;
}
}
temp.UnlockBits(bmpData);
destPictBox.Image = temp;
}

Görüntüyü yeniden boyutlandırmak için aşağıdaki fonksiyonu kullanabilirsiniz. ConstWidth değişkenine istediğiniz değeri vererek işlem sonucundaki görüntünün enini ayarlayabilirsiniz. Ben tüm görüntüleri standart boyuta getirmek için böyle bir yol kullanmıştım. Fonksiyonun çalışmasını kolaylıkla anlayabilir ve istediğiniz en-boy değiştirme işlemini kolayca yapabilirsiniz.


private void ResizeImage(ref Image myImage)
{
float nPercent = ((float)constWidth / myImage.Width);
int sourceWidth = myImage.Width;
int sourceHeight = myImage.Height;
int sourceX = 0;
int sourceY = 0;

int destX = 0;
int destY = 0;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);

Bitmap bmPhoto = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(myImage.HorizontalResolution, myImage.VerticalResolution);

Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.DrawImage(myImage,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
myImage = bmPhoto;
grPhoto.Dispose();
}

Kenar algılama, gürültü yok etme ve yapısal (morfolojik) filtreleri de bir sonraki yazımda paylaşmak üzere. İyi işlemeler diliyorum :)


29 Comments on “C# ile Görüntü İşleme – 1”

  1. 1 C# ile Görüntü İşleme - 2 | Ahmet Kakıcı said at 16:31 on January 2nd, 2009:

    […] önce görüntü okuma, gösterme ve kaydetme gibi başlıca fonksiyonları vermiştim. Aşağıda ise asıl görüntüyü işeyecek fonksiyonlar bulunmaktadır. Tabii buradaki […]

  2. 2 Anonymous said at 11:31 on March 23rd, 2009:

    çok teşekkürler hocam…

  3. 3 C# ile Görüntü İşleme - 3 | Ahmet Kakıcı said at 11:27 on June 4th, 2009:

    […] iki yazının ardından ( 1 – 2 ) sonunda üçüncü yazıyı da yazabildim. Bu yazıya sadece morfolojik filtreler kaldı. […]

  4. 4 taemmyheas said at 00:11 on May 11th, 2010:

    meraba bi sorum olacaktı. c#ta grafiği resıme nasıl donusturebiliriz. yardımcı olursanız sevınırım.

  5. 5 Ahmet Kakıcı said at 12:48 on May 14th, 2010:

    Soruyu biraz daha açabilir misiniz ?

  6. 6 Emrah Hançer said at 17:25 on June 1st, 2010:

    Ahmet Kardeş,
    greyPixelArray[i, j] = (int)((double)ptr[0] * 0.3 + (double)ptr[1] * 0.59 + (double)ptr[2] * 0.11);

    0.3 ile 0.11 i yerdeğiştirerek yazmak gerekli. Bu hata tam 3 saatime mal oldu. Kolay gelsin…

  7. 7 Ahmet Kakıcı said at 21:32 on June 1st, 2010:

    Emrah katsayıların seçimi tamamen sana kalmış. İstersen toplayıp üçe de bölebilirdin.

  8. 8 feridun said at 18:18 on June 25th, 2010:

    hocam slm.
    C# ile H.263 ve H.264 ya da open source ya da webM ile msn yapılabilirse performansı sizce ne olur? bide tasarım kalıpları türkçe kaynak elinizde varmı ?

  9. 9 Ahmet Kakıcı said at 19:50 on June 25th, 2010:

    Performansı anlamanın en iyi yolu denemek olacaktır :)
    Tasarım kalıpları için yan tarafta da bağlantısı bulunan Emre Çevik’in sitesine göz atabilirsin:
    http://code.internet.com.tr/kategori/php/designpatterns/

  10. 10 feridun said at 23:14 on June 25th, 2010:

    hocam teşekkürler…

  11. 11 selami said at 04:21 on August 27th, 2010:

    eline sağlık verdiğin bilgiler için…

    resim için seçilen bir bölgenin kes kopyala yapıştır işlemlerinin yapılması hakkında bir çalışman oldu mu acaba ?
    olduysa eğer, bunu paylaşman çok faydalı olacaktır.

  12. 12 Ahmet Kakıcı said at 12:15 on August 28th, 2010:

    Kesme işlemi için çalışacağınız pikselleri uç noktalardan değil arada alacağınız noktalardan seçerseniz yapabilirsiniz.

  13. 13 oki said at 15:24 on December 7th, 2010:

    Öncelikle picturebox nesnesinden diziye dönüşüm işlemini yapan fonksiyonu verelim:

    yazmıssınız ama benim pictureBox1 de hata veriyor “a field initializer cannot referance the non-static field method or propety “diye yazıyor çözüm nedir magdurum

  14. 14 Ahmet Kakıcı said at 20:47 on December 7th, 2010:

    oki
    http://pastebin.ca/
    adresine kodunu gönderip link verirsen bakabilirim.

  15. 15 Ali said at 17:51 on February 8th, 2011:

    Ben kodlarınızı deniyorum, ama width,height olaylarında kodlar hata veriyor…

  16. 16 melih said at 00:11 on March 15th, 2011:

    guzelmisss

  17. 17 mas otmasyon said at 16:44 on April 25th, 2011:

    bmpData.Stride – bmpData.Width * 3;
    ile ne yapıyoruz

  18. 18 Çağrı said at 12:50 on May 11th, 2011:

    yazdıklarınız benim seviyemdeki bir programcı için mükemmel bir kaynak oldu teşekkürler.

  19. 19 Java hex islemleri hakkinda. said at 23:18 on June 23rd, 2011:

    […] […]

  20. 20 esma said at 13:52 on July 11th, 2011:

    merhabalar c sharpta bir resmi istenilen parçalara nasıl böleriz mesela 300-400 boyutundaki bir resmi 30-4o parçalara ayırmak gibi yardımcı olursanız sevinirim :))

  21. 21 Anonymous said at 10:22 on March 1st, 2012:

    […] […]

  22. 22 Enis said at 20:22 on November 3rd, 2012:

    Gerçekten güzel bilgi. Daha önce resim işleme ile ilgili kodlama yapmadığım için bana gerçekten faydası dokundu. Bilgi ancak paylaşılınca “Bilgi” adını alır.. Emeğinize sağlık.

  23. 23 Ali Ates said at 10:55 on December 12th, 2012:

    Hocam ellerinize sağlık öncelikle.

    Bir sorum olacaktı, son fonksiyonda şöyle bir satır var:

    float nPercent = ((float)constWidth / myImage.Width);

    “constWidth” den kastınız nedir? tanımlamadığınız bu değişkeni başka bir fonksiyondan mı almalıyız? derleyici altını çizdiğinde farkettim, yardımcı olursanız sevinirim.

  24. 24 Ahmet Kakıcı said at 11:01 on December 13th, 2012:

    O değişken ile ilgili bilgiyi yazıda vermiştim: “Görüntüyü yeniden boyutlandırmak için aşağıdaki fonksiyonu kullanabilirsiniz. ConstWidth değişkenine istediğiniz değeri vererek işlem sonucundaki görüntünün enini ayarlayabilirsiniz”

  25. 25 ömer said at 11:40 on May 20th, 2013:

    hocam ben bir resimdeki belirli pixellerin renk kontrolünü yapmağa başladım ama bir çok noktada takıldım örneğin picturebox nesnesindeki resmin herhangi bir bir pixelini rgb kodu ile alma hakkından yardımcı olabilirmisiniz
    teşekkürler

  26. 26 halil said at 00:52 on July 6th, 2013:

    hocam merhaba ben asp.nette görüntülü online proje yapmak istiyorum nasıl yardımcı olabilirsiniz

  27. 27 vedat said at 22:40 on July 11th, 2013:

    Emeğinize sağlık gerçekten çok faydalı bilgiler anlatımda güzel olmuş başarılar dilerim

  28. 28 Ferhan said at 13:53 on April 7th, 2014:

    merhaba kameradan görüntü almak ve o görüntüyü frame şeklinde resim resim kaydetmek için yukarıdaki örneğinizi kullanıyorum (bunun için ayrıca teşekkür ederim ) fakat olmuyor yardımcı olur musunuz …

  29. 29 Kenan said at 11:08 on May 17th, 2014:

    Şöyle bir gözden geçirdim. unsafe ve pointer görünce C# ile görüntü işlenmeyeceğinin ispatı gibi olmuş dedim. Ama ciddiye alma.


Leave a Reply