Thẻ

, , , , , ,

My new Blog: hoangvancong.com

Xử lý ảnh cơ bản với C#: https://www.youtube.com/watch?v=k7n4IVEnmrE
Cách tạo histogram với C#: https://www.youtube.com/watch?v=7mbYVH58kqk

Để thực hiện cân bằng mức xám ta cần thực hiện qua 4 bước sau.

Bước 1: Probability Mass Function (PMF) (Tính xác xuất)

Ta xét ví dụ với Histogram sau:

namlunoy_histogram

Ta thấy h(64) = 40, h(128) = 30, h(255) = 40. Và có tất cả 110 điểm ảnh.

Trước tiên ta cần tính được xác xuất xuất hiện của các mức xám trong ảnh.

namlunoy_histogram_probability

Sau bước 1 ta có tần xuất xuất hiện hay xác xuất của các mức xám tương ứng.

p(64) = 40/110
p(128) = 30/110
p(255) = 40/110

Bước 2: Cumulative Distributive Function

Bước này chỉ đơn giản là cộng dồn tần xuất của mức xám hiện tại với tần xuất của các mức xám trước nó. Ta có CDF tương ứng với PMF phía trên như sau:

namlunoy_histogram_cumulative

Ta thấy:
c(64) = 40/110
c(128) = 30/110 + 40/110 = 70/110
c(255) = 40/110 + 70/110 = 1

Bước 3: Multiplize

Trong bước này chúng ta sẽ nhân CDF của mức xám với giá trị max của mức xám ở đây là 255.
Tương ứng với ví dụ trên ta có kết quả như sau:

m(64) = 40/110 * 255 = 92
m(128) = 70/110 * 255 = 162
m(255) = 1 * 255 = 255

Kết quả sau khi nhận được bước này là độ xám mới của các mức xám.

Bước 4: Mapping

Bước này chúng ta chuyển đổi tất cả các pixel có độ xám mới.

Điểm có mức xám 64 chuyển hết thành 92,
Điểm có mức xám 128 chuyển hết thành 162,
Điểm có mức xám 255 chuyển hết thành 255.

Kết quả:

namlunoy_histogram_2
Source code:

  public static Bitmap HistogramEqualization(Bitmap s)
        {
            Bitmap source = (Bitmap)s.Clone();

            BitmapData data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadWrite, source.PixelFormat);
            byte* p = (byte*)data.Scan0;
            int offset = data.Stride - source.Width * 3;
            int total = source.Width * source.Height;

            //Bước 1: Probability Mass Function (PMF): Tính tần số
            float[] xacsuat = new float[256];
            int[] count = new int[256];
            for (int hang = 0; hang < source.Height; hang++)
            {
                for (int cot = 0; cot < source.Width; cot++)
                {
                    count[p[2]]++;
                    p += 3;
                }
                p += offset;
            }

            for (int level = 0; level < 256; level++)
                xacsuat[level] = count[level] * 1.0f / total;

            //Bước 2: Cumulative Distributive Function (CDF)
            float[] cdf = new float[256];
            cdf[0] = xacsuat[0];
            for (int level = 1; level < 256; level++)
                cdf[level] = cdf[level - 1] + xacsuat[level];

            //Bước 3: Multiple
            int[] newLevel = new int[256];
            for (int level = 0; level < 256; level++)
                newLevel[level] = (int)(255 * cdf[level]);

            //Bước 4: Mapping
            p = (byte*)data.Scan0;
            for (int hang = 0; hang < source.Height; hang++)
            {
                for (int cot = 0; cot < source.Width; cot++)
                {
                    p[0] = p[1] = p[2] = (byte)newLevel[p[2]];
                    p += 3;
                }
                p += offset;
            }
            source.UnlockBits(data);
            return source;
        }

Test

Ảnh trước – Ảnh sau

Unequalized       Equalized

Test_Equalization

Link project:
https://www.dropbox.com/s/9u8qmfvnjhdwwo2/HistogramEqualization.rar?dl=0
Tham khảo:
http://en.wikipedia.org/wiki/Histogram_equalization
http://fourier.eng.hmc.edu/e161/lectures/contrast_transform/node2.html
http://www.tutorialspoint.com/dip/Histogram_Equalization.htm

Advertisements