Nadesłany przez Tomasz Lubiński, 15 listopada 2019 21:19
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
Histogram/Form1.cs:
//Wyznaczanie i wyrównywanie Histogramu //(c) 2019 by Tomasz Lubinski //www.algorytm.org using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Imaging; namespace Histogram { public partial class Form1 : Form { private int[] red = null; private int[] green = null; private int[] blue = null; /// <summary> /// Zainicjuj /// </summary> public Form1() { InitializeComponent(); } /// <summary> /// Wczytaj obraz /// </summary> private void wczytaj_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "Otwórz obraz"; dlg.Filter = "Obrazy (*.jpg;*.gif;*.png;*.bmp)|*.jpg;*.gif;*.png;*.bmp"; if (dlg.ShowDialog() == DialogResult.OK) { //Wczytaj plik picture.Image = new Bitmap(dlg.OpenFile()); picture.Height = picture.Image.Height; picture.Width = picture.Image.Width; this.ClientSize = new System.Drawing.Size(Math.Max(picture.Width + 30, 345), picture.Height + 155); //Oblicz histogram red = new int[256]; green = new int[256]; blue = new int[256]; for (int x = 0; x < picture.Width; x++) { for (int y = 0; y < picture.Height; y++) { Color pixel = ((Bitmap)picture.Image).GetPixel(x, y); red[pixel.R]++; green[pixel.G]++; blue[pixel.B]++; } } //Wyswietl histogram na wykresie chart.Series["red"].Points.Clear(); chart.Series["green"].Points.Clear(); chart.Series["blue"].Points.Clear(); for (int i = 0; i < 256; i++) { chart.Series["red"].Points.AddXY(i, red[i]); chart.Series["green"].Points.AddXY(i, green[i]); chart.Series["blue"].Points.AddXY(i, blue[i]); } chart.Invalidate(); } dlg.Dispose(); } /// <summary> /// Oblicza tablice LUT dla histogramu podanej składowej /// </summary> /// <param name="values">histogram dla składowej</param> /// <returns>tablica LUT do wyrównania histogramu</returns> private int[] calculateLUT(int[] values, int size) { //poszukaj wartości minimalnej - czyli pierwszej niezerowej wartosci dystrybuanty double minValue = 0; for (int i = 0; i < 256; i++) { if (values[i] != 0) { minValue = values[i]; break; } } //przygotuj tablice zgodnie ze wzorem int[] result = new int[256]; double sum = 0; for (int i = 0; i < 256; i++) { sum += values[i]; result[i] = (int)(((sum - minValue) / (size - minValue)) * 255.0); } return result; } /// <summary> /// Wyrownywanie Histogramu /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void process_Click(object sender, EventArgs e) { //Sprawdz czy wczytano obraz if (red == null) { return; } //Tablice LUT dla skladowych int[] LUTred = calculateLUT(red, picture.Image.Width * picture.Image.Height); int[] LUTgreen = calculateLUT(green, picture.Image.Width * picture.Image.Height); int[] LUTblue = calculateLUT(blue, picture.Image.Width * picture.Image.Height); //Przetworz obraz i oblicz nowy histogram red = new int[256]; green = new int[256]; blue = new int[256]; Bitmap oldBitmap = (Bitmap)picture.Image; Bitmap newBitmap = new Bitmap(oldBitmap.Width, oldBitmap.Height, PixelFormat.Format24bppRgb); for (int x = 0; x < picture.Width; x++) { for (int y = 0; y < picture.Height; y++) { Color pixel = oldBitmap.GetPixel(x, y); Color newPixel = Color.FromArgb(LUTred[pixel.R], LUTgreen[pixel.G], LUTblue[pixel.B]); newBitmap.SetPixel(x, y, newPixel); red[newPixel.R]++; green[newPixel.G]++; blue[newPixel.B]++; } } picture.Image = newBitmap; //Wyswietl histogram na wykresie chart.Series["red"].Points.Clear(); chart.Series["green"].Points.Clear(); chart.Series["blue"].Points.Clear(); for (int i = 0; i < 256; i++) { chart.Series["red"].Points.AddXY(i, red[i]); chart.Series["green"].Points.AddXY(i, green[i]); chart.Series["blue"].Points.AddXY(i, blue[i]); } chart.Invalidate(); } } }