Beispiel #1
0
 public Bgra32Image HistogramEqualization()
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.histogram_equalization(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #2
0
 public Bgra32Image BilinearTransform(double deltaX, double deltaY, double angle, double scale)
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.bilinear_transform(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, (float)deltaX, (float)deltaY, (float)angle, (float)scale);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #3
0
 public Bgra32Image Quantize(uint lv)
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.quantize(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, lv);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #4
0
 public Gray8Image MorphologyCorrode()
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.morphology_corrode(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #5
0
 public Bgra32Image Sample(uint rate)
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.sample(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, rate);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #6
0
 public Gray8Image GrayProcessing(uint bit)
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.mask(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, bit);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #7
0
        public static string Bitmap2string(BitmapSource img)
        {
            /* 转换图片为灰度图并拆分为数组 */

            var gray8_img = new Gray8Image(img);

            var pixels = gray8_img.ImagePixels;
            var info   = gray8_img.Info;

            /* 转换图片像素数组转化为字符画 */
            /* 如果 buffer 长度不够,将不会执行转换 */

            var length = (uint)((info.Width + 2) * (info.Height >> 1));
            var buffer = new byte[length];

            ImgFunc.img2txt(pixels, (uint)info.Width, (uint)info.Height, buffer, ref length);

            /*
             * [How to convert byte[] to string?](http://stackoverflow.com/questions/1003275/how-to-convert-byte-to-string)
             */

            var ret = System.Text.Encoding.UTF8.GetString(buffer, 0, (int)length);

            return(ret);
        }
Beispiel #8
0
 public Gray8Image ContrastStretching(float a, float b)
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.contrast_stretching(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, a, b);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #9
0
 public Gray8Image LogarithmicTransformation(float c, float v)
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.logarithmic_transformation(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, c, v);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #10
0
 public Gray8Image GammaCorrection(float r, float eps)
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.gamma_correction(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, r, eps);
     this.imgPixels = buffer;
     return(this);
 }
Beispiel #11
0
 public Gray8Image Threshold(uint min, uint max)
 {
     byte[] buffer = new byte[imgPixels.Length];
     ImgFunc.threshold(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, min, max);
     this.imgPixels = buffer;
     return(this);
 }
        private void LoadImg(BitmapSource img)
        {
            /*
             * 笔记:
             *
             * 最开始尝试使用 System.drawing 实现转换为 byte,想了想还是算了(各种转化),这些是当时的资料
             * 参考资料:
             * [Convert a bitmap into a byte array](http://stackoverflow.com/questions/7350679/convert-a-bitmap-into-a-byte-array?lq=1)
             * [System.drawing namespace not found under console application](http://stackoverflow.com/questions/8553136/system-drawing-namespace-not-found-under-console-application)
             *
             * 最后决定还是直接转换 BitmapImage 到 byte[]
             *
             * 然后翻了一下这个 [BitmapImage to byte[]](http://stackoverflow.com/questions/6597676/bitmapimage-to-byte)
             * (虽然最后并没有用上,但是知道了如何转换 BitmapImage 的格式)
             *
             * 最后,参考资料:
             * [Finding specific pixel colors of a BitmapImage](http://stackoverflow.com/questions/1176910/finding-specific-pixel-colors-of-a-bitmapimage)
             * 这里强行把图片换成了 PixelFormats.Bgra32,同时使用 CopyPixels 获取各个像素信息到 byte[] 中,
             * 这样就可以交给外部方法处理了。
             */

            /* 保存 Bgra32 版本的像素 */
            bgraImgSrc = new Bgra32Image(img);
            //BgraImgNow = new Bgra32Image(BgraImgSrc);

            /* 保存 8bit 灰度图的版本 */
            gray8ImgSrc = new Gray8Image(img);

            /* 根据图片大小,确定是否实时计算 */
            realtimeProcessing = (img.PixelWidth * img.PixelHeight) < (imgWidMax * imgHgtMax);

            /* 确定采样的上限值 */
            sliderSampling.Maximum = Math.Max(img.PixelWidth, img.PixelHeight);

            /* 调整窗口大小 */
            ResizeForImg(this.imgSrc);

            /* 显示原图像 */
            OriginImg(this.imgSrc);

            /* 启用 保存 按钮 */
            try {
                if (ImgFunc.is_loaded())
                {
                    EnbaleComponent();
                }

                /* 刷新直方图 */
                UpdateHistogram();
            } catch (Exception e) {
                MessageBox.Show(
                    e.Message,
                    "加载 ImgFuncLib 时发生错误",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error
                    );
            }
        }
        /**************** 以上是 频域滤波 的处理部分 ****************/

        /**************** 以下是 选项卡切换选项 的处理部分 ****************/

        /*
         * 参考资料:
         * 响应,切换选项卡:
         * [Is there Selected Tab Changed Event in the standard WPF Tab Control](http://stackoverflow.com/questions/772841/is-there-selected-tab-changed-event-in-the-standard-wpf-tab-control)
         */

        private void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!(e.Source is TabControl) || this.imgSrc == null)
            {
                return;
            }

            if (tabItem_Origin.IsSelected)
            {
                OriginImg(this.imgSrc);
            }
            else if (tabItem_Quantization.IsSelected)
            {
                this.imageView.Source
                      = this.imgRes
                      = new Bgra32Image(this.bgraImgSrc).Quantize((uint)this.sliderQuantization.Value).ToBitmapSource();
            }
            else if (tabItem_Sampling.IsSelected)
            {
                this.imageView.Source
                      = this.imgRes
                      = new Bgra32Image(this.bgraImgSrc).Sample((uint)this.sliderSampling.Value).ToBitmapSource();
            }
            else if (tabItem_Binary.IsSelected)
            {
                this.imageView.Source
                      = this.imgRes
                      = new Gray8Image(this.gray8ImgSrc).GrayProcessing((uint)this.sliderGray8.Value).ToBitmapSource();
            }
            else if (tabItem_Img2txt.IsSelected)
            {
                this.imgTxt = ImgFunc.Bitmap2string(this.imgRes);
            }
            else if (tabItem_PointOps.IsSelected)
            {
                this.imageView.Source
                      = this.imgRes
                      = new Gray8Image(this.gray8ImgSrc).GrayProcessing(0).ToBitmapSource();
            }
            else if (tabItem_HistogramEqualization.IsSelected)
            {
                this.imageView.Source
                      = this.imgRes
                      = new Bgra32Image(this.bgraImgSrc).HistogramEqualization().ToBitmapSource();
            }
            else if (tabItem_Transform.IsSelected)
            {
                this.TransformReset();
            }
            else if (tabItem_Filter.IsSelected)
            {
                /* 更新 数据表格 */
                datagrid_FilterMatrix.ItemsSource = ImgFunc.ConvertArray2DToDataTable(filter_matrix).AsDataView();
            }

            UpdateHistogram();
        }
        private void datagrid_FilterMatrix_CurrentCellChanged(object sender, EventArgs e)
        {
            /*
             * [Convert and use DataTable in WPF DataGrid?]
             * (http://stackoverflow.com/questions/6984686/convert-and-use-datatable-in-wpf-datagrid)
             */

            var table = ((DataView)datagrid_FilterMatrix.ItemsSource).ToTable();

            filter_matrix = ImgFunc.ConvertDataTableToArray2D <double>(table);

            if (realtimeProcessing)
            {
                buttonFilterCalc_Click(null, null);
            }
        }
Beispiel #15
0
        public Gray8Image Histogram(out ImageSource histogram, out int mean, out int mid, out int sd, out int sum)
        {
            var cnt  = new uint[256u];
            var data = new uint[4u];

            ImgFunc.histogram(imgPixels, (uint)imgInfo.Width, (uint)imgInfo.Height, cnt, data);

            histogram = ImgFunc.GenerateHistogram(cnt);

            /* data[] 分别:{灰度均值,灰度中值,灰度方差,像素总数} */
            mean = (int)data[0];
            mid  = (int)data[1];
            sd   = (int)data[2];
            sum  = (int)data[3];

            return(this);
        }
Beispiel #16
0
        public Bgra32Image Filter(string opName)
        {
            var buffer = new byte[imgPixels.Length];

            switch (opName)
            {
            case "roberts": ImgFunc.filter_roberts(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height); break;

            case "sobel": ImgFunc.filter_sobel(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height); break;

            case "median": ImgFunc.filter_median(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height); break;

            default: throw new Exception("No such Filter!");
            }

            this.imgPixels = buffer;
            return(this);
        }
        private void buttonFilter_Click(object sender, RoutedEventArgs e)
        {
            if (!(e.Source is Button))
            {
                return;
            }

            if (e.Source == button_FilterIncreaseCol)
            {
                filter_matrix_wid += 2;
                if (filter_matrix_wid > 1)
                {
                    button_FilterReduceCol.IsEnabled = true;
                }
            }
            else if (e.Source == button_FilterReduceCol)
            {
                filter_matrix_wid -= 2;
                if (filter_matrix_wid <= 1)
                {
                    button_FilterReduceCol.IsEnabled = false;
                }
            }
            else if (e.Source == button_FilterIncreaseRow)
            {
                filter_matrix_hgt += 2;
                if (filter_matrix_hgt > 1)
                {
                    button_FilterReduceRow.IsEnabled = true;
                }
            }
            else if (e.Source == button_FilterReduceRow)
            {
                filter_matrix_hgt -= 2;
                if (filter_matrix_hgt <= 1)
                {
                    button_FilterReduceRow.IsEnabled = false;
                }
            }

            filter_matrix = ImgFunc.ResizeArray2D(filter_matrix, filter_matrix_wid, filter_matrix_hgt);

            datagrid_FilterMatrix.ItemsSource = ImgFunc.ConvertArray2DToDataTable(filter_matrix).AsDataView();
        }
Beispiel #18
0
        public Bgra32Image Filter(float[] mat, uint wid, uint hgt)
        {
            /* 针对 int 版本的优化(不过可能没什么明显价值?) */
            bool allInteger = true;

            foreach (var num in mat)
            {
                /* [How to determine if a decimal/double is an integer?]
                 * (http://stackoverflow.com/questions/2751593/how-to-determine-if-a-decimal-double-is-an-integer)
                 */
                if (num % 1 != 0)
                {
                    allInteger = false;
                    break;
                }
            }

            var buffer = new byte[imgPixels.Length];

            if (allInteger)
            {
                var int_matrix = new int[mat.Length];
                for (int i = 0; i < mat.Length; i++)
                {
                    int_matrix[i] = (int)mat[i];
                }
                ImgFunc.filter(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, int_matrix, wid, hgt);
            }
            else
            {
                ImgFunc.filter(imgPixels, buffer, (uint)imgInfo.Width, (uint)imgInfo.Height, mat, wid, hgt);
            }

            this.imgPixels = buffer;
            return(this);
        }
        private void comboBox_Filter_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.Source == comboBox_Filter)
            {
                switch (comboBox_Filter.SelectedIndex)
                {
                case 0: { filter_matrix = new double[, ] {
                              { 0, -1, 0 },
                              { -1, 4, -1 },
                              { 0, -1, 0 },
                          }; break; }

                case 1: { filter_matrix = new double[, ] {
                              { 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0 },
                              { 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0 },
                              { 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0 },
                          }; break; }

                case 2: { filter_matrix = new double[, ] {
                              { 1 / 10.0, 1 / 10.0, 1 / 10.0 },
                              { 1 / 10.0, 2 / 10.0, 1 / 10.0 },
                              { 1 / 10.0, 1 / 10.0, 1 / 10.0 },
                          }; break; }

                case 3: { filter_matrix = new double[, ] {
                              { 1 / 16.0, 1 / 8.0, 1 / 16.0 },
                              { 1 / 8.0, 1 / 4.0, 1 / 8.0 },
                              { 1 / 16.0, 1 / 8.0, 1 / 16.0 },
                          }; break; }

                case 4: { filter_matrix = new double[, ] {
                              { 0, -1, 0 },
                              { -1, 5, -1 },
                              { 0, -1, 0 },
                          }; break; }

                case 5: { filter_matrix = new double[, ] {
                              { -1, -1, -1 },
                              { -1, 9, -1 },
                              { -1, -1, -1 },
                          }; break; }

                case 6: { filter_matrix = new double[, ] {
                              { 1, -2, 1 },
                              { -2, 5, -2 },
                              { 1, -2, 1 },
                          }; break; }

                case 7: { filter_matrix = new double[, ] {
                              { 0, 0, 0 },
                              { -1, 1, 0 },
                              { 0, 0, 0 },
                          }; break; }

                case 8: { filter_matrix = new double[, ] {
                              { 0, -1, 0 },
                              { 0, 1, 0 },
                              { 0, 0, 0 },
                          }; break; }

                case 9: { filter_matrix = new double[, ] {
                              { -1, 0, 0 },
                              { 0, 1, 0 },
                              { 0, 0, 0 },
                          }; break; }

                case 10: { filter_matrix = new double[, ] {
                               { -1, -1, -1, -1, -1 },
                               { 0, 0, 0, 0, 0 },
                               { 1, 1, 1, 1, 1 },
                           }; break; }

                case 11: { filter_matrix = new double[, ] {
                               { -1, 0, 1 },
                               { -1, 0, 1 },
                               { -1, 0, 1 },
                               { -1, 0, 1 },
                               { -1, 0, 1 },
                           }; break; }

                case 12: { filter_matrix = new double[, ] {
                               { -1, 0, -1 },
                               { 0, 4, 0 },
                               { -1, 0, -1 },
                           }; break; }

                case 13: { filter_matrix = new double[, ] {
                               { -1, -1, -1 },
                               { -1, 8, -1 },
                               { -1, -1, -1 },
                           }; break; }

                case 14: { filter_matrix = new double[, ] {
                               { -1, -1, -1 },
                               { -1, 9, -1 },
                               { -1, -1, -1 },
                           }; break; }

                case 15: { filter_matrix = new double[, ] {
                               { 1, -2, -1 },
                               { -2, 4, -2 },
                               { 1, -2, -1 },
                           }; break; }

                default: break;
                }

                datagrid_FilterMatrix.ItemsSource = ImgFunc.ConvertArray2DToDataTable(filter_matrix).AsDataView();
                if (realtimeProcessing)
                {
                    buttonFilterCalc_Click(null, null);
                }
            }
            else if (e.Source == comboBox_FilterOther)
            {
                BitmapSource img = null;
                switch (comboBox_FilterOther.SelectedIndex)
                {
                case 0: img = new Bgra32Image(this.bgraImgSrc).Filter("median").ToBitmapSource(); break;

                case 1: img = new Bgra32Image(this.bgraImgSrc).Filter("roberts").ToBitmapSource(); break;

                case 2: img = new Bgra32Image(this.bgraImgSrc).Filter("sobel").ToBitmapSource(); break;
                }
                if (img != null)
                {
                    this.imageView.Source = this.imgRes = img;
                }
            }
        }
        public static BitmapImage OpenImgFileWithHuffmanCoding(string filePath = null)
        {
            if (filePath == null)
            {
                var dlg = new Microsoft.Win32.OpenFileDialog()
                {
                    DefaultExt = "*.hfm",
                    Filter     = "Binary File with Huffman Coding (*.hfm)|*.hfm"
                };

                if ((bool)dlg.ShowDialog())
                {
                    filePath = dlg.FileName;
                }
            }


            if (filePath != null)
            {
                /*
                 * 参考资料:
                 * [BitmapImage sourceStream is null in WPF]
                 * (http://stackoverflow.com/questions/17838006/bitmapimage-sourcestream-is-null-in-wpf)
                 */
                byte[] src = File.ReadAllBytes(filePath);

                /* 转换结果 */
                var buf         = new byte[src.Length * 8];
                var actual_size = ImgFunc.huffman_decode(src, (uint)src.Length, buf, (uint)buf.Length);

                /* 检查转换是否出现错误 */
                if (actual_size < 0)
                {
                    string message;
                    switch (actual_size)
                    {
                    case -1: { message = "这不是一个有效的哈夫曼压缩文件"; break; }

                    case -2: { message = "无法建立哈夫曼树进行解码"; break; }

                    case -3: { message = "解码所分配的缓冲区不足,无法继续解码"; break; }

                    case -4: { message = "文件数据不完整,无法继续解码"; break; }

                    default: { message = "未知的错误"; break; }
                    }

                    System.Windows.MessageBox.Show(
                        message,
                        "无法打开文件",
                        System.Windows.MessageBoxButton.OK,
                        System.Windows.MessageBoxImage.Error
                        );
                    return(null);
                }

                var img = new BitmapImage();
                try {   /* 尝试初始化图像 */
                    img.BeginInit();
                    img.StreamSource = new MemoryStream(buf, 0, actual_size);
                    img.EndInit();
                } catch (System.InvalidOperationException) {
                    System.Windows.MessageBox.Show(
                        "未能识别这个文件类型",
                        "不支持的文件",
                        System.Windows.MessageBoxButton.OK,
                        System.Windows.MessageBoxImage.Error
                        );
                    img = null;
                }

                return(img);
            }

            return(null);
        }
        public static void SaveImgFileWithHuffmanCoding(BitmapSource img)
        {
            /*
             * 关于转换方法:
             * [Data type conversion: BitmapImage to binary or byte[]]
             * (https://social.msdn.microsoft.com/Forums/vstudio/en-US/a47b89c0-b1a2-4212-96bb-63e4d9cbe319/data-type-conversion-bitmapimage-to-binary-or-byte?forum=netfxbcl)
             */

            byte[] buf;
            int    actual_size;
            {   /* 开始转换 */
                byte[]           src;
                BmpBitmapEncoder encoder = new BmpBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(img));
                using (MemoryStream ms = new MemoryStream()) {
                    encoder.Save(ms);
                    src = ms.ToArray();
                }

                /* 转换结果 */
                buf         = new byte[src.Length + 4096];
                actual_size = ImgFunc.huffman_encode(src, (uint)src.Length, buf, (uint)buf.Length);

                /* 检查转换是否出现错误 */
                if (actual_size < 0)
                {
                    string message;
                    switch (actual_size)
                    {
                    case -3:
                    case -1: { message = "内部错误,缓冲区分配不足"; break; }

                    case -2: { message = "内部错误,创建哈夫曼树失败"; break; }

                    default: { message = "未知的错误"; break; }
                    }

                    System.Windows.MessageBox.Show(
                        message,
                        "保存文件失败",
                        System.Windows.MessageBoxButton.OK,
                        System.Windows.MessageBoxImage.Error
                        );
                    return;
                }
            }

            var dlg = new Microsoft.Win32.SaveFileDialog()
            {
                DefaultExt = "*.hfm",
                Filter     = "Binary File with Huffman Coding (*.hfm)|*.hfm"
            };

            var result = dlg.ShowDialog();

            if (result == true)
            {
                var fs = File.Open(dlg.FileName, FileMode.Create);
                fs.Write(buf, 0, actual_size);
                fs.Close();
            }
        }