ayrilmiş pixelleri silme (isolated pixels)

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
sr1111
Üye
Mesajlar: 220
Kayıt: 06 Mar 2008 01:59

ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen sr1111 »

2 renkli 1 bit lik resmimde birbirinden ayrilmiş bütün 1 veya 2 pixel buyuklugundeki siyah noktalari scanline kullanarak silmek istiyorum. nokta sagindan solundan ustunden altindan diğer siyah pixellerle birleşmemesi lazım. Yardimci olacak arkadaslara tesekkur ederim.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen mrmarman »

Scanline nasıl kullanılır ? Sorunusun cevabı sizin sorunun da cevabı. İşlem aslında çok basittir.

(1) iki tane iç içe döngü kuracaksınız. Birincisi y (dikey) ikincisi x (yatay)
(2) y döngüsü 0'dan başlayıp bitmap height-1 kadar olacak.
(3) her döngü adımında bir PByteArray tipindeki diziye bytearray := bitmap.Scanline[y]; şeklinde tüm satırı bir kerede atayacaksınız.
(4) bu döngü adımında iç döngüyü (x) kuracak 1 bitlik resim olduğuna göre direk 0'dan başlayıp Bitmap.Width-1 kadar gidecek.
(5) Değer 0'a eşit ise siyah, 255'e eşit ise beyazdır diyeceksiniz.

(*) Geriye bu matriksin her bir siyah olanının sağı, solu, üstü, altı, çaprazı komşusunda siyah var mı iki komşusunda siyah var mı bakıp yorumlamak kalıyor. :idea:
Resim
Resim ....Resim
sr1111
Üye
Mesajlar: 220
Kayıt: 06 Mar 2008 01:59

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen sr1111 »

ustadim bilgi icin tesekkur ederim. fakat dediğiniz sekilde bir kod yazacak kadar ileri seviyede değilim.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen mrmarman »

- Bu durumda daha basit aşamalar ile başlasanız. Keşke direkt Image üzerine yoğunlaşmasaydınız.

- Şimdi size bu konuya ilişkin kodu yazsam bir sonraki aşama için sorunun devamı da gerekecek. O zaman da aynı gerekçe ile yine hazır paket kod istemek durumunda olacaksınız. Nasıl çözüm olacak bilemedim. :?: Birisini sen diğerini o yazsın desek yine anlamsız olacak. Forum forum dolaşıp projeyi modüller halinde bitirmek de olacak gibi değil... Planınız nedir ?
Resim
Resim ....Resim
sr1111
Üye
Mesajlar: 220
Kayıt: 06 Mar 2008 01:59

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen sr1111 »

ustadim devamı gelmez insallah, yapmak istedigim sey.
threshold yaptigim bitmap resimlerde yazilara yakın ve diğer yerlerde kucuk siyahlıklar kaliyor bunlari temizlemek istiyordum.

asagidaki bir kodu inceliyordum. 24 bit icin bana 2 renkli 1 bit lazimdi.
procedure ChangeWhiteToBlack24(var Bitmap: TBitmap);
var
scanline: PRGBTriple;
y: Integer;
x: Integer;
begin
Assert(Bitmap.PixelFormat = pf24bit);
for y := 0 to Bitmap.Height - 1 do
begin
scanline := Bitmap.ScanLine[y];
for x := 0 to Bitmap.Width - 1 do
begin
with scanline^ do
begin
if (rgbtBlue = 255) and (rgbtGreen = 255) and (rgbtRed = 255) then
FillChar(scanline^, sizeof(TRGBTriple), 0);
end;
inc(scanline);
end;
end;
end;
sr1111
Üye
Mesajlar: 220
Kayıt: 06 Mar 2008 01:59

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen sr1111 »

imageen komponentinde boyle bir procedure ImageEnView1.Proc.RemoveIsolatedPixels(0, 4); oldugunu gordum fakat inceledigimde bir bug oldugunu gördüm bildirdim. bir cevap cikmadi.
kodu buraya yazsam duzeltebilirmiyiz.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen mrmarman »

Dediğim gibi, küçücük bir fonksiyon istediğin işi yapar. Yolunu tarif ettim. Üçüncü parti bileşen de aynı yolu kullanacaktır.

Parametre olarak: 4 pixel komşusuna kadar boş ise sil ve 3 tur daha yeniden temizlik yapılacağı geçilir, işlem yapılır.

Asıl konu bunu yapacak yolun kavranmasıdır. Yoksa kod vermek çok kolay. Yazmak 20 dakikayı almaz.
Resim
Resim ....Resim
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen mrmarman »

Sana projeyi göndereyim de en azından bir çıkış noktası bulmak için elinde örnek oluşsun.
Mantık kurmak için elle tutulur örnek bulamadığın için veriyorum. Kod içerisinde açıklamaları ekledim. :idea:

Resim
Resim

Kullanımı :

Kod: Tümünü seç

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  IzoleOlanlariTemizle( Image1 );
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
  Image1.Picture.LoadFromFile( ExtractFilePath(Application.ExeName) + 'orj.bmp' );
end;
Procedure :

Kod: Tümünü seç

procedure IzoleOlanlariTemizle( Image: TImage );
Const
  BitsPerPixel = 1;
Var
  x,y,
  iSonX,iSonY : Integer;
  bitmap      : TBitmap;
  digersatir,
  bizimsatir  : PByteArray;
  k, g, d, b,
  kd, kb,
  gd, gb,
  boolIzole   : Boolean;
begin
  bitmap             := TBitmap.Create;
  bitmap.Width       := Image.Width;
  bitmap.Height      := Image.Height;
  bitmap.Assign( Image.Picture.Bitmap );
  bitmap.PixelFormat := pf8bit;

  iSonX := (Bitmap.Width DIV BitsPerPixel)-1;
  iSonY := bitmap.Height - 1;

  for y := 0 to iSonY do
  begin // satırlar
    bizimsatir := bitmap.Scanline[y];
   for x := 0 to iSonX do
    begin // sütunlar
      if bizimsatir[x] = $00 // Siyah
        then begin
          boolIzole := False; // varsayılan İzole Değildir...
          if  (y > 0) AND (y < iSonY )
          AND (x > 0) AND (x < iSonX )
          then // ilk veya son satır değilse önceki/sonraki satır sorabileceğiz.
          begin
             b := bizimsatir[x-1] <> $00; // batı
             d := bizimsatir[x+1] <> $00; // doğu
            digersatir := bitmap.ScanLine[y-1]; // Önceki Satır.
             k := digersatir[x+0] <> $00; // kuzey
            kb := digersatir[x-1] <> $00; // kuzeybatı
            kd := digersatir[x+1] <> $00; // kuzeydoğu
            digersatir := bitmap.ScanLine[y+1]; // Sonraki Satır.
             g := digersatir[x+0] <> $00; // güney
            gb := digersatir[x-1] <> $00; // güneybatı
            gd := digersatir[x+1] <> $00; // güneydoğu

            // Hepsi TRUE ise her tarafı beyazdır. Yani izoledir. boolIzele TRUE dönecek..
            boolIzole := k and kb and kd and g and gb and gd and b and d;
          end;
          if boolIzole then
          begin // eğer izole ise beyaza çekicez...
            bizimsatir[x] := $ff; // beyaza çektik.
          end;
        end;
    end;
  end;
  Image.Picture.Bitmap.Assign( bitmap );
  Bitmap.Free;
end;
Dosya ekleri
BitmapScanLine_Ornegi.rar
ScanLine ile izole pixel temizleme algoritması örneği
(252.59 KiB) 85 kere indirildi
Resim
Resim ....Resim
sr1111
Üye
Mesajlar: 220
Kayıt: 06 Mar 2008 01:59

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen sr1111 »

Üstadim cok tesekkur ederim çok makbule geçti, uğraştınız.
hep de problemli zamanlarımda siz koşuyorsunuz.

Const
BitsPerPixel = 2;
deneme yaptim 2 pixel de calistiramadim.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen mrmarman »

Bitsperpixel başka bir amaç için. Ona dokunma.
2 pixel komşuluk için içteki k, g, d, b vs. Yönler var ya, onlardan faydalanacaksın. Y-2, Y+2 satırlardaki x-2, x-1, x+0, x+1, x+2 noktalarını kontrol edeceksin. boolIzole ise üzerinde bulunduğun noktayı beyaza çekicen.

Hep merkez konuştuk, çapraz komşu ama diğer yönlerden komşu olmayanları da aynı mantıkla izole sayabilirsin. Hani örnek resimde küçük çizgi alancıklarını etüd ettiğinde akla gelen şeklinde.

Gerisi sana, kaynak resme nasıl baktığın ile ilişkili. Kodu okuyup ona göre çalışma yapmak durumundasınız. Aslında kod kendini anlatıyor. Yukarıda söylediğimden başka bir şey koymadık.
Resim
Resim ....Resim
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen mrmarman »

Merhaba.

- Biraz daha konuya girebilmen için ek bir örnek hazırladım. Başka da vaktim olacak mı bilmiyorum. Şimdilik bu kadar yardımcı olabilirim. :idea:
- Ekteki kaynak kodlarını da eklediğim projede aşağıdaki şekilde yaptığın işlemleri mercek altına alabilirsin.

Resim

- Projeye Mouse ile kaynak resim üzerinde gezerken, kaynak ve hedef resimdeki değişiklikleri orjinal resmin 8'de birini formun büyüklüğü ile orantılı olarak yakınlaştırıp büyüterek gösteren bir kısım da ekledim. Neler dönmüş anlayabilmen için. Mouse nerede ise kırmızı bir çerçeve içerisinde orayı görüyorsun. Büyütürken aspect'i korudum ki yanıltmasın. :idea:

Fonksiyonun yeni hali şöyle:
KomsuPixSayisi değişkenine parametre geçmezsen varsayılan olarak (1) kabul edilir.

Kod: Tümünü seç

procedure IzoleOlanlariTemizle( KaynakImage, HedefImage: TImage; KomsuPixSayisi:Integer = 1 );
Var
  x,y, iSayac,
  iSonX,iSonY : Integer;
  bitmap      : TBitmap;
  digersatir,
  bizimsatir  : PByteArray;
  k, g, d, b,
  kd, kb,
  gd, gb,
  boolIzole   : Boolean;
begin
  bitmap             := TBitmap.Create;
  bitmap.Width       := KaynakImage.Width;
  bitmap.Height      := KaynakImage.Height;
  bitmap.Assign( KaynakImage.Picture.Bitmap );
  bitmap.PixelFormat := pf8bit;

  iSonX := Bitmap.Width  -1;
  iSonY := bitmap.Height -1;

  for y := 0 to iSonY do
  begin // satırlar
    bizimsatir := bitmap.Scanline[y];
   for x := 0 to iSonX do
    begin // sütunlar
      if bizimsatir[x] = $00 // Siyah
        then begin
          boolIzole := False; // varsayılan İzole Değildir...
          if  (y >= KomsuPixSayisi) AND (y <= iSonY-KomsuPixSayisi )
          AND (x >= KomsuPixSayisi) AND (x <= iSonX-KomsuPixSayisi )
          then // Kenar kısımlarında X, Y olarak limitteysek pass geçiyoruz.
          begin
            for iSayac := 1 to KomsuPixSayisi do
            begin
               b := bizimsatir[x-iSayac] <> $00; // batı
               d := bizimsatir[x+iSayac] <> $00; // doğu
              digersatir := bitmap.ScanLine[y-iSayac]; // Önceki Satır.
               k := digersatir[x+0] <> $00; // kuzey
              kb := digersatir[x-iSayac] <> $00; // kuzeybatı
              kd := digersatir[x+iSayac] <> $00; // kuzeydoğu
              digersatir := bitmap.ScanLine[y+iSayac]; // Sonraki Satır.
               g := digersatir[x+0] <> $00; // güney
              gb := digersatir[x-iSayac] <> $00; // güneybatı
              gd := digersatir[x+iSayac] <> $00; // güneydoğu

              // Hepsi TRUE ise her tarafı beyazdır. Yani izoledir. boolIzele TRUE dönecek..
              boolIzole := k and kb and kd and g and gb and gd and b and d;
            end;
          end;
          if boolIzole then
          begin // eğer izole ise beyaza çekicez...
            bizimsatir[x] := $ff; // beyaza çektik.
          end;
        end;
    end;
  end;
  HedefImage.Picture.Bitmap.Assign( bitmap );
  Bitmap.Free;
end;
Kullanımı

Kod: Tümünü seç

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  // Kaynak ile Hedefi ayırdım...
  IzoleOlanlariTemizle( Image1, Image2, 1 );
  // Kaynak ile Hedef aynı ise olanı eski olanın üzerine yazar...
  IzoleOlanlariTemizle( Image2, Image2, 2 );
  IzoleOlanlariTemizle( Image2, Image2, 1 );
  IzoleOlanlariTemizle( Image2, Image2, 2 );
end;
Dosya ekleri
BitmapScanLine_Ornegi.rar
İzole Pixel Temizleme ( Komşu Pixeller )
(253.74 KiB) 79 kere indirildi
Resim
Resim ....Resim
sr1111
Üye
Mesajlar: 220
Kayıt: 06 Mar 2008 01:59

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen sr1111 »

ustadim 1. ornegi bu sekilde timage deb tbitmap e duzelttim. O sekilde kullanmam lazim oldugu icin bir sorun olur mu. Buyuk resimlerde 1-2 kez sorun nerden kaynaklandigini anlayamadim. 2. ornegide inceleyecegim.
procedure Tform.IzoleOlanlariTemizle( bitmap: Tbitmap );
Const
BitsPerPixel = 1;
Var
x,y,
iSonX,iSonY : Integer;
digersatir,
bizimsatir : PByteArray;
k, g, d, b,
kd, kb,
gd, gb,
boolIzole : Boolean;
begin

bitmap.PixelFormat := pf8bit;

iSonX := (Bitmap.Width DIV BitsPerPixel)-1;
iSonY := bitmap.Height - 1;

for y := 0 to iSonY do
begin // satırlar
bizimsatir := bitmap.Scanline[y];
for x := 0 to iSonX do
begin // sütunlar
if bizimsatir[x] = $00 // Siyah
then begin
boolIzole := False; // varsayılan İzole Değildir...
if (y > 0) AND (y < iSonY )
AND (x > 0) AND (x < iSonX )
then // ilk veya son satır değilse önceki/sonraki satır sorabileceğiz.
begin
b := bizimsatir[x-1] <> $00; // batı
d := bizimsatir[x+1] <> $00; // doğu
digersatir := bitmap.ScanLine[y-1]; // Önceki Satır.
k := digersatir[x+0] <> $00; // kuzey
kb := digersatir[x-1] <> $00; // kuzeybatı
kd := digersatir[x+1] <> $00; // kuzeydoğu
digersatir := bitmap.ScanLine[y+1]; // Sonraki Satır.
g := digersatir[x+0] <> $00; // güney
gb := digersatir[x-1] <> $00; // güneybatı
gd := digersatir[x+1] <> $00; // güneydoğu

// Hepsi TRUE ise her tarafı beyazdır. Yani izoledir. boolIzele TRUE dönecek..
boolIzole := k and kb and kd and g and gb and gd and b and d;
end;
if boolIzole then
begin // eğer izole ise beyaza çekicez...
bizimsatir[x] := $ff; // beyaza çektik.
end;
end;
end;
end;

end;
En son sr1111 tarafından 12 Mar 2014 03:18 tarihinde düzenlendi, toplamda 1 kere düzenlendi.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen mrmarman »

Sorun olmaz Image olsa bile zaten procedure içerisinden Bitmap'e dönüştürüp işlem yapıyoruz.

- Bence direkt koda soyunmadan önce, sana verdiğim özellikle ikinci projede; bir kaç örnek resmi alarak istediğin şekilde dönüştürüp dönüştüremediğini test etmelisin. :idea:
Resim
Resim ....Resim
sr1111
Üye
Mesajlar: 220
Kayıt: 06 Mar 2008 01:59

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen sr1111 »

1-
dönüştürdügüm Tbitmap seklindeki procedure orjinalindeki gibi asagidakilerden birini yazinca hata aliyorum. ntdll.dll gibi bir mesaj veriyor. bu yuzden 2 satirida sildimdi.
Bitmap.Assign( bitmap );
Bitmap.Free;

2-
2.ornekte şöyle bir hata goruyorum bana göre pixel buyuklugunu 2 ye ayarladigimda;
3 pixel yan yana yatay seklinde oldugunda ortadaki 1 pixeli siliyor. normalde bunu silmemesi lazim değil mi.
6 pixeli de aynı şekilde ortadaki 2 pixeli siliyor. buna benzer sorunlar var.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: ayrilmiş pixelleri silme (isolated pixels)

Mesaj gönderen mrmarman »

(1) Bitmap zaten procedure içerisinde create edilen ara bir çözüm. Sen parametre olarak Bitmap ismini kullanma.. Örneğin KaynakBitmap:TBitmap şeklinde kullan ki, orjinal halindeki gibi Assign ederken kendi kendini refere etmeyesin. Hatan o olmuş.

(2) Sana çözüm için yol gösteriyorum. Artık elini taşın altına koymanın vakti gelmedi mi ? Komşuluk 2 ise iki sonrasına müstakil olarak bakılır. Sen önce (1) sonra (2) sonra yeniden (1) şeklinde üç pass ile üzerinden geçtiğinde niahi sonucu alırsın. Düşünsene bir nokta silindikten sonra geriye kalanlarda da benzer bir durum yeni baştan doğacaktır. Bunları yeniden değerlendirmen lazım. Sen daha kendi resminden bir örnek paylaşmadığından suya yazı yazıyor olduğumu da hatırlatırım.
Resim
Resim ....Resim
Cevapla