新文章 网摘 文章 随笔 日记

AForge + ZXing识别条形码

namespace ScanQRCode
{
    partial class FormCut
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.TbxResult = new System.Windows.Forms.TextBox();
            this.PboxCover = new System.Windows.Forms.PictureBox();
            this.PboxVideo = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.PboxCover)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.PboxVideo)).BeginInit();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(1360, 12);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "识别";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // TbxResult
            // 
            this.TbxResult.Font = new System.Drawing.Font("PMingLiU", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(136)));
            this.TbxResult.Location = new System.Drawing.Point(1245, 41);
            this.TbxResult.Multiline = true;
            this.TbxResult.Name = "TbxResult";
            this.TbxResult.Size = new System.Drawing.Size(318, 737);
            this.TbxResult.TabIndex = 6;
            // 
            // PboxCover
            // 
            this.PboxCover.Location = new System.Drawing.Point(723, 12);
            this.PboxCover.Name = "PboxCover";
            this.PboxCover.Size = new System.Drawing.Size(493, 309);
            this.PboxCover.TabIndex = 9;
            this.PboxCover.TabStop = false;
            // 
            // PboxVideo
            // 
            this.PboxVideo.Location = new System.Drawing.Point(30, 91);
            this.PboxVideo.Name = "PboxVideo";
            this.PboxVideo.Size = new System.Drawing.Size(946, 654);
            this.PboxVideo.TabIndex = 10;
            this.PboxVideo.TabStop = false;
            // 
            // FormCut
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1613, 790);
            this.Controls.Add(this.PboxVideo);
            this.Controls.Add(this.PboxCover);
            this.Controls.Add(this.TbxResult);
            this.Controls.Add(this.button1);
            this.Name = "FormCut";
            this.Text = "FormCut";
            ((System.ComponentModel.ISupportInitialize)(this.PboxCover)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.PboxVideo)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.TextBox TbxResult;
        private System.Windows.Forms.PictureBox PboxCover;
        private System.Windows.Forms.PictureBox PboxVideo;
    }
}

 

 

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using AForge.Imaging.Filters;
using AForge.Video;
using AForge.Video.DirectShow;

namespace ScanQRCode
{
    public partial class FormCut : Form
    {
        private readonly bool _useStaticFile = false;//是否使用静态图片
        private readonly string _baseDir = $@"{Application.StartupPath}\ImgParts";

        //从文件加载原图
        private Image _originImage;
        public FormCut()
        {
            InitializeComponent();

            DrawCoverRectangle();
            Load += CameraQR_Load;
            if (_useStaticFile)
            {
                _originImage = Image.FromFile($@"{_baseDir}\WeChat 圖片_20230607093025.jpg");
            }
        }
        /// <summary>
        /// 画用于定位的覆盖的矩形
        /// </summary>
        private void DrawCoverRectangle()
        {
            PboxVideo.SizeMode = PictureBoxSizeMode.Zoom;
            PboxCover.BackColor = Color.Transparent;
            PboxCover.Parent = PboxVideo;
            PboxCover.Width = PboxVideo.Width;
            PboxCover.Height = PboxVideo.Height;
            PboxCover.Top = 0;
            PboxCover.Left = 0;
            PboxCover.SizeMode = PictureBoxSizeMode.Zoom;

            Bitmap bitmap = new Bitmap(4656, 3496);
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                g.Clear(Color.Transparent);
                g.Save();
                g.Dispose();
            }

            var rectangles = GetRectangles1();
            foreach (var rectangle in rectangles)
            {
                DrawRectangle(bitmap, rectangle.Rectangle);
            }
            PboxCover.Image = bitmap;

        }

        /// <summary>
        /// 在图片上画矩形
        /// </summary>
        /// <param name="img"></param>
        /// <param name="rectangle"></param>
        public void DrawRectangle(Image img, Rectangle rectangle)
        {
            using (var g = Graphics.FromImage(img))
            {
                Pen pen = new Pen(Color.Red)
                {
                    Width = 5
                };
                g.DrawRectangle(pen, rectangle);
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            if (PboxVideo.Image == null)
            {
                AppendMessage("无法捕获图片");
            }

            ClearResult();

            //逐个切割识别
            var rectangles = GetRectangles1();
            //int i = 0;
            var dir = $@"{_baseDir}\{DateTime.Now:yyyyMMddHHmmssfff}";
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            //保存图片
            string fileName = $@"{dir}\originImage.bmp";
            _originImage = (Image)PboxVideo.Image.Clone();
            PboxVideo.Image.Save(fileName);
            //var xxxx = OCR.Decode((Bitmap)_originImage);


            int maxTryTimes = 8;//每个方向最大尝试次数
            int step = 5;//每次尝试坐标加减的像素
            Rectangle tryRectangle;
            for (int i = 0; i < rectangles.Count; i++)
            {
                var rectangle = rectangles[i];
                //rectangle.X += 26;//假装标签贴往右偏移了20个像素,验证偏移的识别情况
                //rectangle.Y -= 23;//假装标签贴往上偏移了20个像素,验证偏移的识别情况

                //不作偏移原始坐标尝试一次
                string text = OCR.TryDecode(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.InSitu, step, 0, out tryRectangle);
                //_formShowBitmap.DrawRectangle(tryRectangle);

                //尝试向左偏移n次
                if (string.IsNullOrWhiteSpace(text))
                {
                    text = OCR.TryNTimes(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.Left, step, maxTryTimes, out tryRectangle);

                }

                //尝试向上偏移n次
                if (string.IsNullOrWhiteSpace(text))
                {
                    text = OCR.TryNTimes(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.Up, step, maxTryTimes, out tryRectangle);

                }

                //尝试向右偏移n次
                if (string.IsNullOrWhiteSpace(text))
                {
                    text = OCR.TryNTimes(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.Right, step, maxTryTimes, out tryRectangle);

                }

                //尝试向下偏移n次
                if (string.IsNullOrWhiteSpace(text))
                {
                    text = OCR.TryNTimes(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.Down, step, maxTryTimes, out tryRectangle);
                }


                //尝试左上偏移n次
                if (string.IsNullOrWhiteSpace(text))
                {
                    text = OCR.TryNTimes(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.LeftUp, step, maxTryTimes, out tryRectangle);
                }

                //尝试左下偏移n次
                if (string.IsNullOrWhiteSpace(text))
                {
                    text = OCR.TryNTimes(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.LeftDown, step, maxTryTimes, out tryRectangle);
                }

                //尝试右上偏移n次
                if (string.IsNullOrWhiteSpace(text))
                {
                    text = OCR.TryNTimes(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.RightUp, step, maxTryTimes, out tryRectangle);
                }

                //尝试右下偏移n次
                if (string.IsNullOrWhiteSpace(text))
                {
                    text = OCR.TryNTimes(_originImage, rectangle.Rectangle, $@"{dir}\{i}.bmp", Direction.RightDown, step, maxTryTimes, out tryRectangle);
                }

                //显示到文本框中
                if (!string.IsNullOrWhiteSpace(text))
                {
                    AppendMessage(rectangle.Name + ":" + text);
                }
                else
                {
                    AppendMessage("无法识别,请先摆放好位置!");
                    break;
                }
            }
        }


        /// <summary>
        /// 获取各个条码在图片上的坐标区域
        /// </summary>
        /// <returns></returns>

        private List<ElementRectangle> GetRectangles1()
        {
            List<ElementRectangle> rectangles = new List<ElementRectangle>
            {
                new ElementRectangle {Name="SKU",Rectangle=   new Rectangle(1783,572,785,212) },
                new ElementRectangle {Name="Qty",Rectangle= new Rectangle(3018,429,291,225) },
                new ElementRectangle {Name="Team",Rectangle= new Rectangle(2824,652,503,229) },
                new ElementRectangle {Name="XX",Rectangle= new Rectangle(2038,905,992,224) },
                new ElementRectangle {Name="SN1",Rectangle= new Rectangle(1892,1123,485,150) },
                new ElementRectangle {Name="SN2",Rectangle= new Rectangle(2607,1129,549,153) },
                new ElementRectangle {Name="SN3",Rectangle= new Rectangle(1881,1274,498,151) },
                new ElementRectangle {Name="SN4",Rectangle= new Rectangle(2601,1278,553,161) },
                new ElementRectangle {Name="SN5",Rectangle= new Rectangle(1877,1425,500,151) },
                new ElementRectangle {Name="SN6",Rectangle= new Rectangle(2598,1434,555,159) },
                new ElementRectangle {Name="SN7",Rectangle= new Rectangle(1885,1572,485,159) },
                new ElementRectangle {Name="SN8",Rectangle= new Rectangle(2596,1590,549,156) },
                new ElementRectangle {Name="SN9",Rectangle= new Rectangle(1876,1729,497,155) },
                new ElementRectangle {Name="SN10",Rectangle= new Rectangle(2589,1744,562,165) },
                new ElementRectangle {Name="SN11",Rectangle= new Rectangle(1878,1881,491,159) },
                new ElementRectangle {Name="SN12",Rectangle= new Rectangle(2588,1904,560,162) },
                new ElementRectangle {Name="Carton",Rectangle= new Rectangle(1940,2038,1094,294) },
                new ElementRectangle {Name="YY",Rectangle= new Rectangle(2173,2427,623,271) },
                new ElementRectangle {Name = "YY2",Rectangle = new Rectangle(2092,2785,804,209)}
            };
            return rectangles;
        }
        private List<ElementRectangle> GetRectangles2()
        {
            List<ElementRectangle> rectangles = new List<ElementRectangle>
            {
                new ElementRectangle {Name="SKU",Rectangle=   new Rectangle(1695,424,801,222) },
                new ElementRectangle {Name="Qty",Rectangle= new Rectangle(2940,371,253,212) },
                new ElementRectangle {Name="SN1",Rectangle= new Rectangle(2188,1305,546,208) },
                new ElementRectangle {Name="SN2",Rectangle= new Rectangle(2195,1584,546,203) },
                new ElementRectangle {Name="Carton",Rectangle= new Rectangle(1954,1879,1091,339) },
                new ElementRectangle {Name="UPC",Rectangle= new Rectangle(2194,2377,636,250) }
            };
            return rectangles;
        }
        private void CameraQR_Load(object sender, EventArgs e)
        {
            Start();
        }


        private delegate void ClearResultFun();
        private delegate void AppendResultFun(string txt);
        /// <summary>
        /// 清空结果
        /// </summary>
        private void ClearResult()
        {
            if (InvokeRequired)
            {
                ClearResultFun md = ClearResult;
                Invoke(md);
            }
            else
            {
                TbxResult.Text = "";
                TbxResult.Refresh();
            }
        }

        /// <summary>
        /// 追加输出结果
        /// </summary>
        /// <param name="txt"></param>
        private void AppendMessage(string txt)
        {
            if (InvokeRequired)
            {
                AppendResultFun md = AppendMessage;
                Invoke(md, txt);
            }
            else
            {
                TbxResult.AppendText("\r\n");
                TbxResult.AppendText(txt);
                TbxResult.Refresh();
            }
        }

        #region 测试AI生成的代码
        private VideoCaptureDevice _videoSource;
        private ManualResetEvent _frameProcessedEvent;

        void Start()
        {
            // 初始化摄像头
            FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            _videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
            // 设置帧率为30帧/秒
            //videoSource.DesiredFrameRate = 100;
            _videoSource.VideoResolution = _videoSource.VideoCapabilities[0];
            _videoSource.NewFrame += VideoSource_NewFrame;

            // 初始化事件
            _frameProcessedEvent = new ManualResetEvent(false);

            // 启动摄像头
            _videoSource.Start();
        }

        void Stop()
        {
            // 停止摄像头
            _videoSource.SignalToStop();
            _videoSource.WaitForStop();
        }
        private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            // 复制图像以防止在处理过程中被修改
            Bitmap frame = (Bitmap)eventArgs.Frame.Clone();

            // 在新线程中处理图像
            ThreadPool.QueueUserWorkItem(ProcessFrame, frame);

            // 等待图像处理完成
            _frameProcessedEvent.WaitOne();
        }

        private void ProcessFrame(object state)
        {
            try
            {
                // 图像处理逻辑
                Bitmap frame = (Bitmap)state;
                // 在这里进行你的图像处理操作
                // 显示图像(示例:将图像转为灰度并显示)
                Bitmap grayscaleFrame = Grayscale.CommonAlgorithms.BT709.Apply(frame);
                //grayscaleFrame.Show(); // 自定义方法,用于显示图像
                PboxVideo.Image = grayscaleFrame;
                //SetFrameImage(grayscaleFrame);
                // 标记图像处理完成
                _frameProcessedEvent.Set();
            }
            catch (Exception ex)
            {
                Console.WriteLine("An error occurred during image processing: " + ex.Message);
            }
            finally
            {
                // 释放图像资源
                ((Bitmap)state).Dispose();
            }
        }


        #endregion
    }
}

 

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using ZXing;
using ZXing.Common;
using ZXing.Multi;

namespace ScanQRCode
{

    /// <summary>
    /// 偏移方向
    /// </summary>
    public enum Direction
    {
        /// <summary>
        ////// </summary>
        Left,
        /// <summary>
        /// 左上
        /// </summary>
        LeftUp,
        /// <summary>
        /// 左下
        /// </summary>
        LeftDown,
        /// <summary>
        ////// </summary>
        Right,
        /// <summary>
        /// 右上
        /// </summary>
        RightUp,
        /// <summary>
        /// 右下
        /// </summary>
        RightDown,
        /// <summary>
        ////// </summary>
        Up,
        /// <summary>
        ////// </summary>
        Down,
        /// <summary>
        /// 原地不变
        /// </summary>
        InSitu
    }
    public class OCR
    {

        /// <summary>
        /// 上下反转
        /// </summary>
        /// <param name="mybm"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static Bitmap VerticalFlipPic(Bitmap mybm, int width, int height)
        {
            Bitmap bm = new Bitmap(width, height);
            int x, y, z;
            Color pixel;

            for (x = 0; x < width; x++)

            {
                for (y = height - 1, z = 0; y >= 0; y--)
                {
                    pixel = mybm.GetPixel(x, y);//获取当前像素的值
                    bm.SetPixel(x, z++, Color.FromArgb(pixel.R, pixel.G, pixel.B));//绘图
                }
            }
            return bm;//返回翻转后的图片
        }

        /// <summary>
        /// 左右反转
        /// </summary>
        /// <param name="mybm"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static Bitmap HorizontalFlip(Bitmap mybm, int width, int height)
        {
            Bitmap bm = new Bitmap(width, height);//初始化一个记录经过处理后的图片对象
            int x, y, z;//x,y是循环次数,z是用来记录像素点的x坐标的变化的
            Color pixel;



            for (y = height - 1; y >= 0; y--)
            {
                for (x = width - 1, z = 0; x >= 0; x--)
                {
                    pixel = mybm.GetPixel(x, y);//获取当前像素的值
                    bm.SetPixel(z++, y, Color.FromArgb(pixel.R, pixel.G, pixel.B));//绘图
                }
            }
            return bm;//返回经过翻转后的图片
        }

        public static Result[] Decode(Bitmap barcodeBitmap)
        {
            

            MultiFormatReader multiFormatReader = new MultiFormatReader();
            GenericMultipleBarcodeReader multiBarcodeReader = new GenericMultipleBarcodeReader(multiFormatReader);
            LuminanceSource source = new BitmapLuminanceSource(barcodeBitmap);
            BinaryBitmap bBitmap = new BinaryBitmap(new HybridBinarizer(source));
            Result[] zResults = multiBarcodeReader.decodeMultiple(bBitmap);
            return zResults;
        }

      
        /// <summary>
        /// 
        /// </summary>
        /// <param name="barcodeBitmap"></param>
        /// <returns></returns>
        public static Result[] DecodeRgbBitmap(Bitmap barcodeBitmap)
        {
            byte[] buffer;
            BinaryBitmap bBitmap = GetBinaryBitmap(barcodeBitmap, out buffer);
            MultiFormatReader multiFormatReader = new MultiFormatReader();
            GenericMultipleBarcodeReader multiBarcodeReader = new GenericMultipleBarcodeReader(multiFormatReader);
            Result[] zResults = multiBarcodeReader.decodeMultiple(bBitmap);
            return zResults;
        }
        public static Result[] Decode(BinaryBitmap barcodeBitmap)
        {
            MultiFormatReader multiFormatReader = new MultiFormatReader();
            GenericMultipleBarcodeReader multiBarcodeReader = new GenericMultipleBarcodeReader(multiFormatReader);
            Result[] zResults = multiBarcodeReader.decodeMultiple(barcodeBitmap);
            return zResults;
        }

        /// <summary>
        /// 尝试N次
        /// </summary>
        /// <param name="originImage"></param>
        /// <param name="originRectangle"></param>
        /// <param name="fileFullName"></param>
        /// <param name="direction"></param>
        /// <param name="absoluteStep"></param>
        /// <param name="maxTryTimes"></param>
        /// <param name="tryRectangle"></param>
        /// <returns></returns>
        public static string TryNTimes(Image originImage, Rectangle originRectangle, string fileFullName, Direction direction, int absoluteStep, int maxTryTimes,out Rectangle tryRectangle)
        {
            tryRectangle = new Rectangle();
            //尝试向左偏移n次
            int currentTimes = 1;
            string text = null;
            //次数未达到且未能读取到结果
            while (currentTimes <= maxTryTimes && text == null)
            {
                //尝试向左偏移第currentTimes次
                text = TryDecode(originImage, originRectangle, fileFullName, direction, absoluteStep, currentTimes,out tryRectangle);
                currentTimes++;
            }
            return text;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="originImage">原始图片</param>
        /// <param name="originRectangle">原始坐标区域</param>
        /// <param name="fileFullName">剪裁得到的图片保存的全路径文件名</param>
        /// <param name="direction">偏移方向</param>
        /// <param name="absoluteStep">偏移的绝对距离</param>
        /// <param name="tryTimes">尝试偏移次数</param>
        /// <param name="tryRectangle"></param>
        /// <returns></returns>
        public static string TryDecode(Image originImage, Rectangle originRectangle, string fileFullName, Direction direction, int absoluteStep, int tryTimes,out Rectangle tryRectangle)
        {
            //new一个新的,避免因引用改变原数据
            tryRectangle = new Rectangle(originRectangle.X, originRectangle.Y, originRectangle.Width, originRectangle.Height);

            switch (direction)
            {

                case Direction.Left://向左偏移
                case Direction.Right://向右偏移
                    tryRectangle.X += GetStep(direction, absoluteStep) * tryTimes;
                    break;
                case Direction.Up://向上偏移
                case Direction.Down://向下偏移
                    tryRectangle.Y += GetStep(direction, absoluteStep) * tryTimes;
                    break;
                case Direction.LeftUp://向左上偏移
                    tryRectangle.X += GetStep(Direction.Left, absoluteStep) * tryTimes;
                    tryRectangle.Y += GetStep(Direction.Up, absoluteStep) * tryTimes;
                    break;
                case Direction.LeftDown://向左下偏移
                    tryRectangle.X += GetStep(Direction.Left, absoluteStep) * tryTimes;
                    tryRectangle.Y += GetStep(Direction.Down, absoluteStep) * tryTimes;
                    break;
                case Direction.RightUp://向右上偏移
                    tryRectangle.X += GetStep(Direction.Right, absoluteStep) * tryTimes;
                    tryRectangle.Y += GetStep(Direction.Up, absoluteStep) * tryTimes;
                    break;
                case Direction.RightDown://向右下偏移
                    tryRectangle.X += GetStep(Direction.Right, absoluteStep) * tryTimes;
                    tryRectangle.Y += GetStep(Direction.Down, absoluteStep) * tryTimes;
                    break;
                case Direction.InSitu://原地不变
                default:
                    break;
            }

            //剪裁图片
            var imgPart = CropImage(originImage, tryRectangle);

            try
            {
                //OCR.ToGray(imgPart);
                //imgPart= Sharpen(imgPart,0.5);
                imgPart.Save(fileFullName);

                //解码
                var result = Decode(imgPart);
                if (result != null && result.Any())
                {
                    return result[0].Text;
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                imgPart?.Dispose();
                imgPart = null;
            }


            return null;
        }
        /// <summary>
        /// 裁剪图片
        /// </summary>
        /// <param name="originImage">原图片</param>
        /// <param name="region">裁剪的方形区域</param>
        /// <returns>裁剪后图片</returns>
        public static Bitmap CropImage(Image originImage, Rectangle region)
        {
            Bitmap result = new Bitmap(region.Width, region.Height);
            Graphics graphics = Graphics.FromImage(result);
            graphics.DrawImage(originImage, new Rectangle(0, 0, region.Width, region.Height), region, GraphicsUnit.Pixel);
            return result;
        }

        /// <summary>
        /// 根据方向计算步长
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="absoluteStep"></param>
        /// <returns></returns>
        public static int GetStep(Direction direction, int absoluteStep)
        {
            switch (direction)
            {
                case Direction.InSitu:
                    return 0;
                case Direction.Left:
                    return -absoluteStep;
                case Direction.Right:
                    return absoluteStep;
                case Direction.Up:
                    return -absoluteStep;
                case Direction.Down:
                    return absoluteStep;

                default:
                    return absoluteStep;
            }
        }

        /// <summary>
        /// 图像锐化
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static Bitmap Sharpen(Bitmap bitmap, double value)
        {
            int w = bitmap.Width;
            int h = bitmap.Height;
            try
            {
                Bitmap dstBitmap = new Bitmap(w, h, PixelFormat.Format24bppRgb);
                BitmapData srcData = bitmap.LockBits(new Rectangle
                (0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                BitmapData dstData = dstBitmap.LockBits(new Rectangle
                (0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
                unsafe
                {
                    byte* pIn = (byte*)srcData.Scan0.ToPointer();
                    byte* pOut = (byte*)dstData.Scan0.ToPointer();
                    byte* p;
                    int stride = srcData.Stride;
                    for (int y = 0; y < h; y++)
                    {
                        for (int x = 0; x < w; x++)
                        {
                            //边缘八个点像素不变
                            if (x == 0 || x == w - 1 || y == 0 || y == h - 1)
                            {
                                pOut[0] = pIn[0];
                                pOut[1] = pIn[1];
                                pOut[2] = pIn[2];
                            }
                            else
                            {
                                int r0, r1, r2, r3, r4, r5, r6, r7, r8;
                                int g1, g2, g3, g4, g5, g6, g7, g8, g0;
                                int b1, b2, b3, b4, b5, b6, b7, b8, b0;
                                double vR, vG, vB;
                                //左上
                                p = pIn - stride - 3;
                                r1 = p[2];
                                g1 = p[1];
                                b1 = p[0];
                                //正上
                                p = pIn - stride;
                                r2 = p[2];
                                g2 = p[1];
                                b2 = p[0];
                                //右上
                                p = pIn - stride + 3;
                                r3 = p[2];
                                g3 = p[1];
                                b3 = p[0];
                                //
                                p = pIn - 3;
                                r4 = p[2];
                                g4 = p[1];
                                b4 = p[0];
                                //
                                p = pIn + 3;
                                r5 = p[2];
                                g5 = p[1];
                                b5 = p[0];
                                //左下
                                p = pIn + stride - 3;
                                r6 = p[2];
                                g6 = p[1];
                                b6 = p[0];
                                //正下
                                p = pIn + stride;
                                r7 = p[2];
                                g7 = p[1];
                                b7 = p[0];
                                // 右下 
                                p = pIn + stride + 3;
                                r8 = p[2];
                                g8 = p[1];
                                b8 = p[0];
                                //中心点
                                p = pIn;
                                r0 = p[2];
                                g0 = p[1];
                                b0 = p[0];
                                vR = (double)r0 - (double)(r1 + r2 + r3 + r4 + r5 + r6 + r7 + r8) / 8;
                                vG = (double)g0 - (double)(g1 + g2 + g3 + g4 + g5 + g6 + g7 + g8) / 8;
                                vB = (double)b0 - (double)(b1 + b2 + b3 + b4 + b5 + b6 + b7 + b8) / 8;
                                vR = r0 + vR * value;
                                vG = g0 + vG * value;
                                vB = b0 + vB * value;
                                if (vR > 0)
                                {
                                    vR = Math.Min(255, vR);
                                }
                                else
                                {
                                    vR = Math.Max(0, vR);
                                }

                                if (vG > 0)
                                {
                                    vG = Math.Min(255, vG);
                                }
                                else
                                {
                                    vG = Math.Max(0, vG);
                                }

                                if (vB > 0)
                                {
                                    vB = Math.Min(255, vB);
                                }
                                else
                                {
                                    vB = Math.Max(0, vB);
                                }
                                pOut[0] = (byte)vB;
                                pOut[1] = (byte)vG;
                                pOut[2] = (byte)vR;

                            }
                            pIn += 3;
                            pOut += 3;
                        }
                        pIn += srcData.Stride - w * 3;
                        pOut += srcData.Stride - w * 3;
                    }
                }
                bitmap.UnlockBits(srcData);
                dstBitmap.UnlockBits(dstData);

                return dstBitmap;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 将彩色图片转换为灰阶图片
        /// </summary>
        /// <param name="bitmap"></param>
        public static void ToGray(Bitmap bitmap)
        {
            for (int x = 0; x < bitmap.Width; x++)
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    Color pixel = bitmap.GetPixel(x, y);
                    int val = (pixel.R + pixel.G + pixel.B) / 3;
                    bitmap.SetPixel(x, y, Color.FromArgb(val, val, val));
                }
            }
        }

        /// <summary>
        /// 处理图片灰度
        /// </summary>
        /// <param name="original"></param>
        /// <returns></returns>
        public static Bitmap MakeGrayscale(Bitmap original)
        {
            //create a blank bitmap the same size as original
            Bitmap newBitmap = new Bitmap(original.Width, original.Height);
            //get a graphics object from the new image
            Graphics g = Graphics.FromImage(newBitmap);
            //create the grayscale ColorMatrix
            ColorMatrix colorMatrix = new ColorMatrix(
               new float[][]
              {
                 new float[] {.3f, .3f, .3f, 0, 0},
                 new float[] {.59f, .59f, .59f, 0, 0},
                 new float[] {.11f, .11f, .11f, 0, 0},
                 new float[] {0, 0, 0, 1, 0},
                 new float[] {0, 0, 0, 0, 1}
              });
            //create some image attributes
            ImageAttributes attributes = new ImageAttributes();
            //set the color matrix attribute
            attributes.SetColorMatrix(colorMatrix);
            //draw the original image on the new image
            //using the grayscale color matrix
            g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
               0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
            //dispose the Graphics object
            g.Dispose();
            return newBitmap;
        }


        /// <summary>
        /// 从摄像头捕获二进制图像
        /// </summary>
        /// <returns></returns>
        public static BinaryBitmap GetBinaryBitmap(Bitmap original, out byte[] buffer)
        {
            buffer = null;
            BinaryBitmap bitmap = null;

            if (original == null)
            {
                return null;
            }

            //new一个内存流
            MemoryStream ms = new MemoryStream();
            try
            {
                //把摄像头的图像保存到内存流中
                original.Save(ms, ImageFormat.Bmp);

                //获取内存流的字节
                buffer = ms.GetBuffer();

                //将捕获的图片字节转化为zxing的亮度源
                LuminanceSource source = new RGBLuminanceSource(buffer, original.Width, original.Height);

                //将亮度源使用zxing混合二进制器转化为二进㓡图像
                bitmap = new BinaryBitmap(new HybridBinarizer(source));
                return bitmap;
            }
            catch (Exception ex)
            {
                //ignore
            }
            finally
            {
                //关闭内存流
                ms.Close();
            }

            return bitmap;
        }
        /// <summary>
        /// 保存到文件
        /// </summary>
        /// <param name="fileFullName"></param>
        /// <param name="buffer"></param>
        public static void SaveToFile(string fileFullName, byte[] buffer)
        {
            using (FileStream fs = new FileStream(fileFullName, FileMode.OpenOrCreate))
            {
                BinaryWriter w = new BinaryWriter(fs);
                w.Write(buffer);
                fs.Close();
            }
        }
    }
}

 

using System.Drawing;

namespace ScanQRCode
{
    public class ElementRectangle
    {
        /// <summary>
        /// 元素名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 元素坐标区域
        /// </summary>
        public Rectangle Rectangle { get; set; }
    }
}

 

posted @ 2023-06-07 10:39  岭南春  阅读(47)  评论(0)    收藏  举报