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; }
}
}