开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 18875|回复: 0
收起左侧

[C#图文教程] OpenCvSharp的学习之旅 lesson04/05----Drawing/BaseImageProcessing

[复制链接]
发表于 2019-9-1 16:52:39 | 显示全部楼层 |阅读模式   江苏省常州市
本帖最后由 qingshanlushui 于 2019-9-1 16:55 编辑

lesson04----Drawing内容较少(但很重要),遂决定和lesson05----BaseImageProcessing(图像处理)放到一起......

一/绘图和写字----Drawing
二/图片复制----CopyImage
三/线性图像混合----GraphicalMix
四/图像亮度与对比度的调节----AdjustingColorBlance

至此应当体会到:Photoshop能做到的,编程都可以做到....

本套学习心得,虽不是什么高瞻远瞩,但依旧禁止任何形式的转载or复制(含非商业),如需任何形式的转载or复制,还请论坛留言通知我一下下....

一/绘图和写字


这个应该是比较常用的功能...


  1.         static void Main(string[] args)
  2.         {

  3.             string path = "./data/test.jpg";
  4.             using (Mat zx61 = new Mat(path, ImreadModes.AnyColor))
  5.             {
  6.                
  7.                 Cv2.Line(zx61, 20, 20, 20, 300, new Scalar(255, 255, 255), 5, LineTypes.Link8, 0);//画线
  8.                 //图片,起始x,起始y,终点x,终点y,颜色,宽度,线的类型(参数2 / 3可以合并成Point类型, 3 / 4亦然),小数点处理

  9.                 Cv2.Rectangle(zx61, new Rect(100, 100, 100, 100), new Scalar(255, 255, 255), 5, LineTypes.AntiAlias);//画空心矩形
  10.                 //图片,矩形(起始x, 起始y, 宽, 高),颜色,线宽度,线类型(反锯齿)

  11.                  Cv2.Ellipse(zx61, new Point(zx61.Cols / 2, zx61.Rows / 2), new Size(50, 100), 90, 0, 300, new Scalar(255, 255, 255), 5, LineTypes.Link8);//画空心椭圆
  12.                 //图片,中心点,长轴短轴(相等时为圆),旋转角度,(绘画)起始角度,结束角度,线宽度,线类型(起始角度和结束角度不重合时, 椭圆不一定闭合)

  13.            // 画实心需要调整线的宽度....

  14.             List < Point > pts = new List<Point>//画实心多边形
  15.             {
  16.                 new Point(10,10),
  17.                 new Point(10,150),
  18.                 new Point(50,180),
  19.                 new Point(150,150),
  20.                 new Point(150,10),
  21.                 new Point(10,10)
  22.             };
  23.                 List<List<Point>> pp = new List<List<Point>>() { pts }; //包含几个矩阵,就绘制几个多边形
  24.                 Cv2.FillPoly(zx61, pp, new Scalar(0, 100, 33), LineTypes.Link8, 0, new Point(0, 0));

  25.                 Cv2.PutText(zx61, "Hello,zx61!", new Point(100, 200), HersheyFonts.HersheySimplex, 1, Scalar.All(255), 3, LineTypes.Link8);//写字


  26.                 using (new Window("zx61", WindowMode.AutoSize, zx61))
  27.                 {
  28.                     Cv2.WaitKey();
  29.                 }
  30.             }
  31.          }
复制代码
分别执行结果:

401.png



二/图片复制

理解 rect类型代表的含义...

  1. //BaseImageProcessing
  2.         /// <summary>
  3.         /// 直接复制
  4.         /// 此外还有一种掩码复制,个人以为使用价值不大...可百度
  5.         /// </summary>
  6.         public static void CopyImage()
  7.         {
  8.             using (Mat zx61 = new Mat("./data/test.jpg", ImreadModes.AnyColor))
  9.             {

  10.                 Rect roi = new Rect(100, 100, 100, 100);//首先要用个rect确定我们的兴趣区域在哪
  11.                 Mat ImageROI = new Mat(zx61, roi);//新建一个mat,把roi内的图像加载到里面去。
  12.                 Rect rect = new Rect(0, 0, ImageROI.Rows, ImageROI.Cols);//定义第一个矩阵,前2个参数是要放的位置,后面插入图片的大小
  13.                 Mat pos = new Mat(zx61, rect);
  14.                 ImageROI.CopyTo(pos);

  15.                 Cv2.ImShow("zx61", zx61);
  16.                 Cv2.WaitKey();
  17.             }

  18.         }
复制代码
运行结果:

407.png



三/线性图像混合

以权重的形式混合两张图片/此外还有相加,相乘方法

线性混合条件及公式:

理论:线性混合操作----两个的大小和类型深度必修一致才可以混合,输出的像素值必须在有效范围内()0 --255)之间。

g(x)=(1&#8722;α)f0(x)+αf1(x)  //数学不好的可忽略公式,只记两张图片权重和为1

α:是权重,基数=1。两幅图片各占的比例总量


  1. /// <summary>
  2.         /// 线性图像混合
  3.         /// </summary>
  4.         /// <param name="path1">图像1加载路径</param>
  5.         /// <param name="path2">图像2加载路径</param>
  6.         public static void GraphicalMix(string path1, string path2)
  7.         {
  8.             using (Mat zx61 = new Mat(path1, ImreadModes.AnyColor ))
  9.             using (Mat zx6161 = new Mat(path2, ImreadModes.AnyColor ))
  10.             using (Mat zx616 = new Mat())
  11.             {
  12.                 double alpha = 0.4;//权重
  13.                 if (zx61.Rows == zx6161.Rows && zx61.Cols == zx6161.Cols && zx61.Type() == zx6161.Type())
  14.                 {
  15.                     Cv2.AddWeighted(zx61, alpha, zx6161, (1 - alpha), 0, zx616);//线性混合
  16.                     //Cv2.Add(zx61, zx6161, zx616);//也可以相加,但是效果不好
  17.                     //Cv2.Multiply(zx61, zx6161, zx616); //相乘,不基于权重
  18.                     using (new Window("zx616", WindowMode.AutoSize, zx616))
  19.                     using (new Window("zx61", WindowMode.AutoSize, zx61))
  20.                     using (new Window("zx6161", WindowMode.AutoSize, zx6161))
  21.                     {
  22.                         Cv2.WaitKey();
  23.                     }
  24.                 }
  25.                 else
  26.                 {
  27.                     Console.WriteLine("图片大小类型不一致!!!");
  28.                 }
  29.             }
  30.         }
复制代码
运行结果:

406.png



四/图像亮度和对比度的调节


图像变换有两种操作:


1:点操作 – 像素变换

2:区域操作 --邻域像素操作,图像周围的像素操作

调整图像亮度和对比度属于像素变换的点操作。


图像调整公式:


g(x,y)=αf(x,y)+β  //数学不好的可尝试解读这个soeasy的公式

其中系数α>0,β是增益值

说明:α值越大,像素之间的差值越大,对比度越强烈。 β值是用于提高图片亮度增益值



  1.         /// <summary>
  2.         /// 图像亮度和对比度
  3.         /// </summary>
  4.         /// <param name="path"></param>
  5.         public static void AdjustingColorBlance(string path)
  6.         {
  7.             //读入的图像是RGB 但是像素顺序是BGR
  8.             using (Mat zx61 = Cv2.ImRead(path, ImreadModes.AnyColor))
  9.             using (Mat zx6161 = new Mat(zx61.Size(), zx61.Type()))
  10.             {

  11.                 int height = zx61.Rows;
  12.                 int width = zx61.Cols;
  13.                 int cn = zx61.Channels(); //通道数
  14.                 float alpha = 0.8f; //系数
  15.                 float beta = 60f;  //增益

  16.                 for (int row = 0; row < height; row++)
  17.                 {
  18.                     for (int col = 0; col < width; col++)
  19.                     {
  20.                         if (cn == 1)
  21.                         {
  22.                             float color = zx61.At<float>(row, col);
  23.                             zx6161.Set<float>(row, col, color);
  24.                         }
  25.                         else if (cn == 3)
  26.                         {
  27.                             Vec3b color = new Vec3b
  28.                             {
  29.                                 Item0 = SaturateCast((zx61.At<Vec3b>(row, col).Item0) * alpha + beta), //B
  30.                                 Item1 = SaturateCast((zx61.At<Vec3b>(row, col).Item1) * alpha + beta), //G
  31.                                 Item2 = SaturateCast((zx61.At<Vec3b>(row, col).Item2) * alpha + beta)  //R
  32.                             };

  33.                             //Vec3f color = new Vec3f
  34.                             //{
  35.                             //    Item0 =  SaturateCast((zx61.At<Vec3f>(row, col).Item0) * alpha + beta), //B
  36.                             //    Item1 =  SaturateCast((zx61.At<Vec3f>(row, col).Item1) * alpha + beta), //G
  37.                             //    Item2 =  SaturateCast((zx61.At<Vec3f>(row, col).Item2) * alpha + beta)  //R
  38.                             //};
  39.                             zx6161.Set<Vec3b>(row, col, color);
  40.                         }
  41.                     }
  42.                 }

  43.                 using (new Window("zx6161", WindowMode.AutoSize, zx6161))
  44.                 using (new Window("zx61", WindowMode.AutoSize, zx61))
  45.                 {
  46.                     Cv2.WaitKey();
  47.                 }

  48.             }
  49.         }
  50.         /// <summary>
  51.         /// 转换成byte类型
  52.         /// </summary>
  53.         /// <param name="value"></param>
  54.         /// <returns></returns>
  55.         private static byte SaturateCast(double value)
  56.         {
  57.             var rounded = Math.Round(value, 0);

  58.             if (rounded < byte.MinValue)
  59.             {
  60.                 return byte.MinValue;
  61.             }

  62.             if (rounded > byte.MaxValue)
  63.             {
  64.                 return byte.MaxValue;
  65.             }

  66.             return (byte)rounded;
  67.         }
复制代码


修改系数 和增益值 float alpha = 0.8f; float beta = 60f;

修改系数 和增益值 float alpha = 1.2f; float beta = 80f;


三次运行结果对比:

405.png


不懂公式莫要慌,记得代码也简单.懂了公式莫激动,学习之旅还很长.........

有缘lesson06见.......


本套学习心得,虽不是什么高瞻远瞩,但依旧禁止任何形式的转载or复制(含非商业),如需任何形式的转载or复制,还请论坛留言通知我一下下....



评分

参与人数 1好评 +1 精币 +66 收起 理由
老郭 + 1 + 66 感谢发布原创作品,精易因你更精彩!

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表