algorytm.org

Implementacja w C#



Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Algorytm Stucki'ego - Implementacja w C#
Ocena użytkownikóww: *****  / 0
SłabyŚwietny
Nadesłany przez Tomasz Lubiński, 29 października 2019 21:58
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.

Stucki/Form1.cs:
//Algorytm Stucki'ego
//(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 Stucki
{
    public partial class Form1 : Form
    {

        /// <summary>
        /// Obraz zrodlowy
        /// </summary>
        private Image source;

        /// <summary>
        /// Przesuniecie zeby uniknac ujemnych indeksow w tablicy bledow
        /// </summary>
        private const int shift = 2;

        /// <summary>
        /// Zainicjuj
        /// </summary>
        public Form1()
        {
            source = null;
            InitializeComponent();
        }

        /// <summary>
        /// Wczytaj obraz
        /// </summary>
        private void wczytaj_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Title = "Otwórz obraz";
            dlg.Filter = "pliki jpg (*.jpg)|*.jpg";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                source = new Bitmap(dlg.OpenFile());

                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 + 32, 374), picture.Height + 155);
            }
            dlg.Dispose();
        }

        /// <summary>
        /// Aproksymacja półtonowa - przetwarzenie progowe
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Simple_Click(object sender, EventArgs e)
        {
            //Nie rob nic jezeli obraz jest jeszcze niewczytany
            if (source == null)
            {
                return;
            }

            //Sprawdz format obrazu - sprawdz czy obraz zawiera 3 kanały - RGB
            if (picture.Image.PixelFormat != PixelFormat.Format24bppRgb)
            {
                MessageBox.Show("Nieobsługiwany format pliku!", "Bład", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //Kopiuj obrazek zrodlowy
            Bitmap bitmap = (Bitmap)source.Clone();
            picture.Image = bitmap;

            //Pobierz wartosc wszystkich punktow obrazu
            BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, picture.Width, picture.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
            byte[] pixelValues = new byte[bmpData.Stride * picture.Height];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, pixelValues, 0, pixelValues.Length);

            //Odczytaj wartosc progu
            int threshold = int.Parse(this.threshold.Text);

            //Dla kolejnych punktow obrazu
            for (int i = 0; i < pixelValues.Length / 3; i++)
            {

                //Wartosci kolorow zapisane sa w kolejnosci Blue, Green, Red
                //Odczytaj wartosc punktu (zamien na odcienie szarosci)
                byte value = (byte)(0.299 * pixelValues[3 * i + 2] +
                                    0.587 * pixelValues[3 * i + 1] +
                                    0.114 * pixelValues[3 * i]);

                if (value > threshold)
                {
                    //wartosc punktu wieksza od progu - zamien na kolor bialy
                    pixelValues[3 * i] = 255;
                    pixelValues[3 * i + 1] = 255;
                    pixelValues[3 * i + 2] = 255;
                 }
                 else
                 {
                     //wartosc punktu nie wieksza od progu - zamien na kolor czarny
                     pixelValues[3 * i] = 0;
                     pixelValues[3 * i + 1] = 0;
                     pixelValues[3 * i + 2] = 0;
                 }
            }

            //Wczytaj przetworzony obraz
            System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, bmpData.Scan0, pixelValues.Length);
            bitmap.UnlockBits(bmpData);
            picture.Refresh();
        }

        /// <summary>
        /// Algorytm Stucki'ego
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Stucki_Click(object sender, EventArgs e)
        {
            //Nie rob nic jezeli obraz jest jeszcze niewczytany
            if (source == null)
            {
                return;
            }

            //Sprawdz format obrazu - sprawdz czy obraz zawiera 3 kanały - RGB
            if (picture.Image.PixelFormat != PixelFormat.Format24bppRgb)
            {
                MessageBox.Show("Nieobsługiwany format pliku!", "Bład", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //Kopiuj obrazek zrodlowy
            Bitmap bitmap = (Bitmap)source.Clone();
            picture.Image = bitmap;

            //Pobierz wartosc wszystkich punktow obrazu
            BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, picture.Width, picture.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
            byte[] pixelValues = new byte[bmpData.Stride * picture.Height];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, pixelValues, 0, pixelValues.Length);

            //Odczytaj wartosc progu
            int threshold = int.Parse(this.threshold.Text);

            //Utworz tablice bledow
            double[,] errors = new double[(bmpData.Stride / 3) + 4, picture.Height + 2];

            //Dla kolejnych punktow obrazu
            for (int i = 0; i < pixelValues.Length / 3; i++)
            {
                int error;
                int x = i % (bmpData.Stride / 3); //wspolrzedna x kolejnego punktu
                int y = i / (bmpData.Stride / 3); //wspolrzedna y kolejnego punktu

                //Wartosci kolorow zapisane sa w kolejnosci Blue, Green, Red
                //Odczytaj wartosc punktu (zamien na odcienie szarosci)
                int value = (int)(0.299 * pixelValues[3 * i + 2] +
                                  0.587 * pixelValues[3 * i + 1] +
                                  0.114 * pixelValues[3 * i]);
                value += (int)errors[x + shift, y];

                if (value > threshold)
                {
                    //wartosc punktu wieksza od progu - zamien na kolor bialy
                    pixelValues[3 * i] = 255;
                    pixelValues[3 * i + 1] = 255;
                    pixelValues[3 * i + 2] = 255;
                    error = value - 255;
                }
                else
                {
                    //wartosc punktu nie wieksza od progu - zamien na kolor czarny
                    pixelValues[3 * i] = 0;
                    pixelValues[3 * i + 1] = 0;
                    pixelValues[3 * i + 2] = 0;
                    error = value;
                }

                //rozpropaguj blad zgodnie z algorytmem Stucki'ego
                errors[x + 1 + shift, y] += (error * 8.0 / 42.0);
                errors[x + 2 + shift, y] += (error * 4.0 / 42.0);

                errors[x - 2 + shift, y + 1] += (error * 2.0 / 42.0);
                errors[x - 1 + shift, y + 1] += (error * 4.0 / 42.0);
                errors[x + shift,     y + 1] += (error * 8.0 / 42.0);
                errors[x + 1 + shift, y + 1] += (error * 4.0 / 42.0);
                errors[x + 2 + shift, y + 1] += (error * 2.0 / 42.0);

                errors[x - 2 + shift, y + 2] += (error * 1.0 / 42.0);
                errors[x - 1 + shift, y + 2] += (error * 2.0 / 42.0);
                errors[x + shift,     y + 2] += (error * 4.0 / 42.0);
                errors[x + 1 + shift, y + 2] += (error * 2.0 / 42.0);
                errors[x + 2 + shift, y + 2] += (error * 1.0 / 42.0);
            }

            //Wczytaj przetworzony obraz
            System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, bmpData.Scan0, pixelValues.Length);
            bitmap.UnlockBits(bmpData);
            picture.Refresh();
        }
    }
}
Dodaj komentarz