Gece Fotoğraflarında Kontrast Ayarı: Görüntü İşleme Projesi#1
Görüntü işleme, görsel verileri analiz ederek düzenleme veya geliştirme yapmamıza olanak tanıyan heyecan verici bir alan. Bu alandaki birçok projeden biri, gece karanlığında çekilmiş fotoğrafların kalitesini artırmayı hedefleyen bir uygulama. Bu yazıda, C# ve Visual Studio kullanarak geliştirilmiş bir görüntü işleme projesini ele alacağız.
İÇİNDEKİLER
Proje Özeti
Proje, gece çekilmiş bir fotoğrafın histogramını analiz ederek kontrast ayarlamaları yapma yeteneğine sahip. Ayrıca, parlaklık düzeyini değiştirmek için bir “trackbar” kullanıyor. Bu sayede, düşük ışık koşullarında çekilen fotoğrafların daha net ve canlı hale getirilmesi amaçlanıyor.
Teknolojik Altyapı
Proje, C# programlama dilini ve Visual Studio entegrasyonunu kullanıyor. Görüntü işleme algoritmaları için .NET Framework içinde yer alan kütüphanelerden yararlanılıyor. Bu teknolojik seçimler, hızlı ve etkili bir geliştirme sürecini desteklemeyi amaçlıyor.
Proje Adımları
- Histogram Analizi: İlk adımda, gece karanlığında çekilen fotoğrafın histogramı analiz ediliyor. Bu, görüntünün parlaklık ve kontrast seviyelerini anlamamızı sağlar.
- Kontrast Ayarları: Histogram analizine dayanarak, görüntünün kontrast ayarları yapılıyor. Bu adım, fotoğrafın daha belirgin hale gelmesini sağlar.
- Parlaklık Düzeyi Ayarı: Kullanıcı arayüzünde bulunan bir “trackbar” sayesinde, fotoğrafın parlaklık düzeyi ayarlanabiliyor. Bu kullanıcı dostu özellik, kullanıcının tercihine göre ayarlamalar yapmayı kolaylaştırıyor.
Kullanılan Araçlar ve Özellikler
Projede, kullanıcı dostu bir arayüz ile aşağıdaki araçlar ve özellikler yer alır:
- ToolStripMenu: Uygulamanın ana kontrol merkezi olan menü çubuğu. Resim açma, kaydetme, histogram analizi ve kontrast ayarı gibi işlemlere erişim sağlar.
- PictureBox: Projede üç adet PictureBox kullanılmıştır. Bu alanlarda görüntüler gösterilir.
- Trackbar: İki adet kontrast ayarı için ve bir adet parlaklık ayarı için kullanılan trackbar’lar.
- TextBox: Histogram analizinden elde edilen verileri saklamak ve görüntülemek için kullanılır.
- ListBox: İşlem adımlarını kullanıcıya göstermek ve seçenekleri sunmak için kullanılan bir liste kutusu.
Proje Adımları ve İşlevselliği
Proje, aşağıdaki adımları içerir:
- Resim Açma ve Kaydetme: Kullanıcı, menüden resim açma ve kaydetme işlemlerini gerçekleştirebilir.
- Histogram Analizi: ToolStripMenu’daki histogram butonuna tıklayarak, seçilen görüntünün histogramını elde edebilirsiniz. Bu bilgiler TextBox alanlarına gösterilir.
- Kontrast Ayarı: İki farklı trackbar, kontrast sınırlarını belirlemenize yardımcı olur. Bu sayede, görüntünün netliği ve belirginliği artırılabilir.
- Parlaklık Ayarı: Üçüncü trackbar ile parlaklık ayarını yapabilirsiniz. Bu özellik, görüntünün genel parlaklık düzeyini değiştirmenize olanak tanır.
Kod Blogu
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { List<int> deger; Bitmap newBitmap; Image file; Boolean opened = false; public Form1() { InitializeComponent(); deger = new List<int>(); } //*************RESİM AÇMA KODLARI******************** private void Ac_Btn_Click(object sender, EventArgs e) { try { openFileDialog1.DefaultExt = ".jpg"; openFileDialog1.Filter = "Image Files(*.BMP;*.JPG;*.GIF;*.PNG)|*.BMP;*.JPG;*.GIF;*.PNG|All files (*.*)|*.*"; openFileDialog1.ShowDialog(); String ResminYolu = openFileDialog1.FileName; pictureBox1.Image = Image.FromFile(ResminYolu); } catch { } } //*************RESİM KAYDETME KODLARI******************** private void Kaydet_Btn_Click(object sender, EventArgs e) { SaveFileDialog saveFileDialog1 = new SaveFileDialog(); saveFileDialog1.Filter = "Jpeg Resmi|*.jpg|Bitmap Resmi|*.bmp|Gif Resmi|*.gif"; saveFileDialog1.Title = "Resmi Kaydet"; saveFileDialog1.ShowDialog(); if (saveFileDialog1.FileName != "") //Dosya adı boş değilse kaydedecek. { // FileStream nesnesi ile kayıtı gerçekleştirecek. FileStream DosyaAkisi = (FileStream)saveFileDialog1.OpenFile(); switch (saveFileDialog1.FilterIndex) { case 1: pictureBox2.Image.Save(DosyaAkisi, System.Drawing.Imaging.ImageFormat.Jpeg); break; case 2: pictureBox2.Image.Save(DosyaAkisi, System.Drawing.Imaging.ImageFormat.Bmp); break; case 3: pictureBox2.Image.Save(DosyaAkisi, System.Drawing.Imaging.ImageFormat.Gif); break; } DosyaAkisi.Close(); } } //*************RESİMİN HİSTOGRAMINI ALMA KODLARI******************** private void Histogtram_Btn_Click(object sender, EventArgs e) { ArrayList DiziPiksel = new ArrayList(); int OrtalamaRenk = 0; Color OkunanRenk; int R = 0, G = 0, B = 0; Bitmap GirisResmi; GirisResmi = new Bitmap(pictureBox1.Image); int ResimGenisligi = GirisResmi.Width; int ResimYuksekligi = GirisResmi.Height; int i = 0; //piksel sayısı tutulacak. for (int x = 0; x < GirisResmi.Width; x++) { for (int y = 0; y < GirisResmi.Height; y++) { OkunanRenk = GirisResmi.GetPixel(x, y); OrtalamaRenk = (int)(OkunanRenk.R + OkunanRenk.G + OkunanRenk.B) / 3; DiziPiksel.Add(OrtalamaRenk); //Resimdeki tüm noktaları diziye atıyor. } } int[] DiziPikselSayilari = new int[256]; for (int r = 0; r < 255; r++) //256 tane renk tonu için dönecek. { int PikselSayisi = 0; for (int s = 0; s < DiziPiksel.Count; s++) //resimdeki piksel sayısınca dönecek. { if (r == Convert.ToInt16(DiziPiksel[s])) PikselSayisi++; } DiziPikselSayilari[r] = PikselSayisi; } int RenkMaksPikselSayisi = 0; //Grafikte y eksenini ölçeklerken kullanılacak. int EnKucukRenkDegeri = 255; int EnBuyukRenkDegeri = 0; for (int k = 0; k <= 255; k++) { if (DiziPikselSayilari[k] > 10) { if (k > EnBuyukRenkDegeri) EnBuyukRenkDegeri = k; if (k < EnKucukRenkDegeri) EnKucukRenkDegeri = k; } listBox1.Items.Add("Renk:" + k + "=" + DiziPikselSayilari[k]); if (DiziPikselSayilari[k] > RenkMaksPikselSayisi) { RenkMaksPikselSayisi = DiziPikselSayilari[k]; } } X1txt.Text = EnKucukRenkDegeri.ToString(); X2txt.Text = EnBuyukRenkDegeri.ToString(); Y1txt.Text = "0"; Y2txt.Text = "255"; Graphics CizimAlani; Pen Kalem1 = new Pen(System.Drawing.Color.DarkRed, 1); Pen Kalem2 = new Pen(System.Drawing.Color.White, 2); CizimAlani = pictureBox3.CreateGraphics(); int GrafikYuksekligi = 400; double OlcekY = (double)ResimYuksekligi / (double)RenkMaksPikselSayisi; double OlcekX = (double)ResimGenisligi / 255.0; int X1 = 0, Y1 = 0, X2 = 0, Y2 = 0; for (int x = 0; x <= 255; x++) { X1 = Convert.ToInt16(x * OlcekX); Y1 = ResimYuksekligi + 30; X2 = X1; Y2 = ResimYuksekligi - (int)(DiziPikselSayilari[x] * OlcekY); CizimAlani.DrawLine(Kalem1, X1, Y1 - 45, ResimYuksekligi, Y1 - 45); CizimAlani.DrawLine(Kalem1, X1, Y1 - 45, X2, Y2 - 45); if (x % 50 == 0) CizimAlani.DrawLine(Kalem2, X1, Y1, X2, 0); } } //*************KONTRAST AYARLARINI YAPMA KODU******************** private void Kontrast_Btn_Click(object sender, EventArgs e) { Color OkunanRenk, DonusenRenk; int R = 0, G = 0, B = 0; Bitmap GirisResmi, CikisResmi; GirisResmi = new Bitmap(pictureBox1.Image); int ResimGenisligi = GirisResmi.Width; int ResimYuksekligi = GirisResmi.Height; CikisResmi = new Bitmap(ResimGenisligi, ResimYuksekligi); int X1, X2, Y1, Y2; X1 = Convert.ToInt16(X1txt.Text); X2 = Convert.ToInt16(X2txt.Text); Y1 = Convert.ToInt16(Y1txt.Text); Y2 = Convert.ToInt16(Y2txt.Text); int i = 0, j = 0; //Çıkış resminin x ve y si olacak. for (int x = 0; x < ResimGenisligi; x++) { for (int y = 0; y < ResimYuksekligi; y++) { OkunanRenk = GirisResmi.GetPixel(x, y); R = OkunanRenk.R; G = OkunanRenk.G; B = OkunanRenk.B; int Gri = (R + G + B) / 3; //*********** Kontras Formülü*************** int X = Gri; int Y = ((((X - X1) * Y2 - Y1)) / (X2 - X1)) + Y1; if (Y > 255) Y = 255; if (Y < 0) Y = 0; DonusenRenk = Color.FromArgb(Y, Y, Y); CikisResmi.SetPixel(x, y, DonusenRenk); } } pictureBox2.Image = CikisResmi; } //*************KONTRAST AYARLARINI YAPMA KODU MANUEL DEGİŞİKLİK******************** private void KontrastAyarla1_Scroll(object sender, EventArgs e) { X1txt.Text = KontrastAyarla1.Value.ToString(); } private void KontrastAyarla2_Scroll(object sender, EventArgs e) { X2txt.Text = KontrastAyarla2.Value.ToString(); } //*************PARLAKLIK AYARINI YAPMA KODU******************** private void PARLAKLIKARTTIR_Scroll(object sender, EventArgs e) { int R = 0, G = 0, B = 0; Color OkunanRenk, DonusenRenk; Bitmap GirisResmi, CikisResmi; GirisResmi = new Bitmap(pictureBox1.Image); int ResimGenisligi = GirisResmi.Width; //GirisResmi global tanımlandı. int ResimYuksekligi = GirisResmi.Height; CikisResmi = new Bitmap(ResimGenisligi, ResimYuksekligi); //Cikis resmini oluşturuyor. Boyutları giriş resmi ile aynı olur. int i = 0, j = 0; //Çıkış resminin x ve y si olacak. for (int x = 0; x < ResimGenisligi; x++) { j = 0; for (int y = 0; y < ResimYuksekligi; y++) { OkunanRenk = GirisResmi.GetPixel(x, y); int parlak = PARLAKLIKARTTIR.Value; R = OkunanRenk.R + parlak; G = OkunanRenk.G + parlak; B = OkunanRenk.B + parlak; //Renkler 255 geçtiyse son sınır olan 255 alınacak. if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255; DonusenRenk = Color.FromArgb(R, G, B); CikisResmi.SetPixel(i, j, DonusenRenk); j++; } i++; } pictureBox2.Image = CikisResmi; } //***********************BİTİŞŞ.... } } |
Ekran Çıktısı

Deneyimler ve Öğrenilenler
Projenin geliştirilme süreci, görüntü işleme ve kullanıcı arayüzü tasarımı konusunda bir dizi deneyim sunuyor. Özellikle histogram analizi ve kontrast ayarları gibi işlemler, görüntü işleme algoritmalarının pratiğe döküldüğü önemli aşamalardır.
Gelecek Planları
Proje, daha da geliştirilebilir birçok özelliği barındırıyor. Örneğin, otomatik kontrast ayarı veya renk dengeleme gibi geliştirmeler projenin özgünlüğünü artırabilir. Ayrıca, farklı görüntü işleme algoritmalarının projeye entegre edilmesi de düşünülebilir. Bu yazının hazırlanmasında referans alınan kaynak İbrahim Çayıroğlu’nun ders notlarıdır. Kendisine verdiği eğitimden dolayı teşekkür ederim.
