22 Mart 2014 Cumartesi

C# ile Histogram Eşitleme

Öncelikle histogram nedir ne işe yarar?
     Histogram bir resimdeki renk değerlerinin sayılarını gösteren grafiktir. Histogram dengeleme veya eşitleme de bir resimdeki renk değerlerinin belli bir yerde kümelenmiş olmasından kaynaklanan renk dağılımı bozukluğunu gidermek için kullanılan bir yöntemdir. Bu yöntem, her resmi iyileştirmez. Yalnızca tüm pixellerin belli araklıkta renk değerine sahip olduğu resimlerde etkilidir.

     Resim gri ve tonlarından oluşuyorsa sorun yok, ama eğer renkli bir resim üzerine bu yöntem uygulanacaksa ve RGB değerleri ile işlem yapılıyorsa o zaman rekleri ayrıştırıp, kırmızı, mavi, yeşil renklerinin her biri için ayrı ayrı histogram dengeleme yapılmalıdır.

Uygulanması :
     İlk önce resmin histogramını elde etmemiz lazım. Bunun için 256 elemanlı bir dizi tanımlayıp, resmin tüm pixellerini gezmemiz lazım. Pixelleri tararken, dizimizin her bir indisine rastlandığında o indise karşılık gelen elemanı bir arttırıyoruz. Yani yaptığımız şey, resim üzerinde 0’dan 255’e kadar olan renk değerlerini saymak. Bu iş bittikten sonra elimizde resmin histogramı bulunmuş oluyor. İstersek bunu grafiğe döküp histogramının dengeli olup olmadığını kontrol edebiliriz. Resmin çok aydınlık ya da çok parlak olduğu kabul edilirse;

     İkinci adım kümülatif (cumulative) histogramı bulmak. Kümülatif histogram, her renk değerinin, kendisinde önceki renk değerleri ile toplanmasından elde edilir. Örneğin eğer resimde 0 değerli pixel sayısı 5, 1 değerli pixel sayısı 20 ise, kümülatif histogramı içinde tutacak dizinin 1 değerine karşılık gelen elemanı 15+25=40 değerine sahip olmalı. Bu işlemi tüm değerler için (0-255) tamamladıktan sonra artık elimizde kümülatif histogram da var.
Sırada normalizasyon adımı var. Bu adımda kümülatif histogramın her değerini, resimde olmasını istediğimiz en büyük değer ile çarpıp pixel sayısına bölüyoruz. Ve sonuçta her renk değerinin normalize edilmiş rengine ulaşıyoruz. Bu adımı da tüm renk değerlerine uygulamayı ihmal etmiyoruz ve artık histogram dengeleme işini bitirmiş oluyoruz.
Son olarak dengelenmiş renkleri resmimize yansıtıyoruz. Bunun için resmin tüm pixellerini tekrar tarayıp, her pixeli, normalize edilmiş renk dizimizde, renk değerine karşılık gelen değer ile boyuyoruz.





C# Kodu 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Histogram_Eşitleme
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void dosyaAçToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();
            string dosyaadi = openFileDialog1.FileName;
            pictureBox1.Image =new Bitmap(dosyaadi);
        }

        private void histogramToolStripMenuItem_Click(object sender, EventArgs e)
        {
            chart1.Series.Clear();
            chart2.Series.Clear();
            chart2.Series.Add("Pixel");
            chart1.Series.Add("Pixel");
            Bitmap resim;
            resim = (Bitmap)pictureBox1.Image;
            int[] h = new int[256];
            for (int i = 0; i < pictureBox1.Width; i++)
            {
                for (int j = 0; j < pictureBox1.Height; j++)
                {
                    Color renk = resim.GetPixel(i, j);
                    int ort = (renk.R + renk.B + renk.G) / 3;
                    h[ort] = h[ort] + 1;
                }
            }
            for (int k = 0; k < 256; k++)
            {
                chart1.Series["Pixel"].Points.AddXY(k, h[k]);
            }
        }

        private void histogramEşitlemeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            chart1.Series.Clear();
            chart2.Series.Clear();
            chart2.Series.Add("Pixel");
            chart1.Series.Add("Pixel");

            Bitmap resim1 = (Bitmap)pictureBox1.Image;
            Bitmap resim2 = (Bitmap)pictureBox1.Image;

            double pixelsayisi = pictureBox1.Width * pictureBox1.Height;
            double[] hist = new double[256];
            double[] c = new double[256];

            for (int i = 0; i < pictureBox1.Width; i++)
            {
                for (int j = 0; j < pictureBox1.Height; j++)
                {
                    Color renk = resim1.GetPixel(i, j);
                    int ort = (renk.R + renk.B + renk.G) / 3;
                    hist[ort] = hist[ort] + 1;
                }
            }
            for (int l = 0; l < 256; l++)
            {
                chart1.Series["Pixel"].Points.AddXY(l, hist[l]);
            }
            for (int i = 0; i < 255; i++)
            {
                c[i] = hist[i] / pixelsayisi;
            }
            for (int i = 0; i < 256; i++)
            {
                if (i==0)
                {
                    c[i] = Math.Floor(c[i] * 255);
                }
                else
                {
                    c[i] = Math.Floor(c[i] * 255 + c[i - 1]);
                }              
            }
            for (int i = 0; i < resim1.Width; i++)
            {
                for (int j = 0; j < resim1.Height; j++)
                {
                    Color renk = resim1.GetPixel(i, j);
                    int r = renk.R;
                    int g = renk.G;
                    int b = renk.B;
                    resim2.SetPixel(i, j, Color.FromArgb(Convert.ToInt32(c[r]*255/256),                                                         Convert.ToInt32(c[g]*255/256), Convert.ToInt32(c[b]*255/256)));
                }
            }            
            pictureBox2.Image = resim2;
            int[] hist2 = new int[255];
            for (int i = 0; i < pictureBox1.Width; i++)
            {
                for (int j = 0; j < pictureBox1.Height; j++)
                {
                    Color renk = resim2.GetPixel(i, j);
                    int deger = (renk.R + renk.B + renk.G) / 3;
                    hist2[deger] = hist2[deger] + 1;
                }
            }
            for (int i = 0; i < 255; i++)
            {
                chart2.Series["Pixel"].Points.AddXY(i, hist2[i]);
            } 
        }
    }
}



1 yorum: