|
本帖最后由 qingshanlushui 于 2019-9-1 16:55 编辑
lesson04----Drawing内容较少(但很重要),遂决定和lesson05----BaseImageProcessing(图像处理)放到一起......
一/绘图和写字----Drawing
二/图片复制----CopyImage
三/线性图像混合----GraphicalMix
四/图像亮度与对比度的调节----AdjustingColorBlance
至此应当体会到:Photoshop能做到的,编程都可以做到....
本套学习心得,虽不是什么高瞻远瞩,但依旧禁止任何形式的转载or复制(含非商业),如需任何形式的转载or复制,还请论坛留言通知我一下下....
一/绘图和写字
这个应该是比较常用的功能...
- static void Main(string[] args)
- {
- string path = "./data/test.jpg";
- using (Mat zx61 = new Mat(path, ImreadModes.AnyColor))
- {
-
- Cv2.Line(zx61, 20, 20, 20, 300, new Scalar(255, 255, 255), 5, LineTypes.Link8, 0);//画线
- //图片,起始x,起始y,终点x,终点y,颜色,宽度,线的类型(参数2 / 3可以合并成Point类型, 3 / 4亦然),小数点处理
- Cv2.Rectangle(zx61, new Rect(100, 100, 100, 100), new Scalar(255, 255, 255), 5, LineTypes.AntiAlias);//画空心矩形
- //图片,矩形(起始x, 起始y, 宽, 高),颜色,线宽度,线类型(反锯齿)
- 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);//画空心椭圆
- //图片,中心点,长轴短轴(相等时为圆),旋转角度,(绘画)起始角度,结束角度,线宽度,线类型(起始角度和结束角度不重合时, 椭圆不一定闭合)
- // 画实心需要调整线的宽度....
- List < Point > pts = new List<Point>//画实心多边形
- {
- new Point(10,10),
- new Point(10,150),
- new Point(50,180),
- new Point(150,150),
- new Point(150,10),
- new Point(10,10)
- };
- List<List<Point>> pp = new List<List<Point>>() { pts }; //包含几个矩阵,就绘制几个多边形
- Cv2.FillPoly(zx61, pp, new Scalar(0, 100, 33), LineTypes.Link8, 0, new Point(0, 0));
- Cv2.PutText(zx61, "Hello,zx61!", new Point(100, 200), HersheyFonts.HersheySimplex, 1, Scalar.All(255), 3, LineTypes.Link8);//写字
- using (new Window("zx61", WindowMode.AutoSize, zx61))
- {
- Cv2.WaitKey();
- }
- }
- }
复制代码分别执行结果:
二/图片复制
理解 rect类型代表的含义...
- //BaseImageProcessing
- /// <summary>
- /// 直接复制
- /// 此外还有一种掩码复制,个人以为使用价值不大...可百度
- /// </summary>
- public static void CopyImage()
- {
- using (Mat zx61 = new Mat("./data/test.jpg", ImreadModes.AnyColor))
- {
- Rect roi = new Rect(100, 100, 100, 100);//首先要用个rect确定我们的兴趣区域在哪
- Mat ImageROI = new Mat(zx61, roi);//新建一个mat,把roi内的图像加载到里面去。
- Rect rect = new Rect(0, 0, ImageROI.Rows, ImageROI.Cols);//定义第一个矩阵,前2个参数是要放的位置,后面插入图片的大小
- Mat pos = new Mat(zx61, rect);
- ImageROI.CopyTo(pos);
- Cv2.ImShow("zx61", zx61);
- Cv2.WaitKey();
- }
- }
复制代码运行结果:
三/线性图像混合
以权重的形式混合两张图片/此外还有相加,相乘方法
理论:线性混合操作----两个的大小和类型深度必修一致才可以混合,输出的像素值必须在有效范围内()0 --255)之间。
g(x)=(1−α)f0(x)+αf1(x) //数学不好的可忽略公式,只记两张图片权重和为1
α:是权重,基数=1。两幅图片各占的比例总量
- /// <summary>
- /// 线性图像混合
- /// </summary>
- /// <param name="path1">图像1加载路径</param>
- /// <param name="path2">图像2加载路径</param>
- public static void GraphicalMix(string path1, string path2)
- {
- using (Mat zx61 = new Mat(path1, ImreadModes.AnyColor ))
- using (Mat zx6161 = new Mat(path2, ImreadModes.AnyColor ))
- using (Mat zx616 = new Mat())
- {
- double alpha = 0.4;//权重
- if (zx61.Rows == zx6161.Rows && zx61.Cols == zx6161.Cols && zx61.Type() == zx6161.Type())
- {
- Cv2.AddWeighted(zx61, alpha, zx6161, (1 - alpha), 0, zx616);//线性混合
- //Cv2.Add(zx61, zx6161, zx616);//也可以相加,但是效果不好
- //Cv2.Multiply(zx61, zx6161, zx616); //相乘,不基于权重
- using (new Window("zx616", WindowMode.AutoSize, zx616))
- using (new Window("zx61", WindowMode.AutoSize, zx61))
- using (new Window("zx6161", WindowMode.AutoSize, zx6161))
- {
- Cv2.WaitKey();
- }
- }
- else
- {
- Console.WriteLine("图片大小类型不一致!!!");
- }
- }
- }
复制代码运行结果:
四/图像亮度和对比度的调节
图像变换有两种操作:
1:点操作 – 像素变换
2:区域操作 --邻域像素操作,图像周围的像素操作
调整图像亮度和对比度属于像素变换的点操作。
图像调整公式:
g(x,y)=αf(x,y)+β //数学不好的可尝试解读这个soeasy的公式
其中系数α>0,β是增益值
说明:α值越大,像素之间的差值越大,对比度越强烈。 β值是用于提高图片亮度增益值
- /// <summary>
- /// 图像亮度和对比度
- /// </summary>
- /// <param name="path"></param>
- public static void AdjustingColorBlance(string path)
- {
- //读入的图像是RGB 但是像素顺序是BGR
- using (Mat zx61 = Cv2.ImRead(path, ImreadModes.AnyColor))
- using (Mat zx6161 = new Mat(zx61.Size(), zx61.Type()))
- {
- int height = zx61.Rows;
- int width = zx61.Cols;
- int cn = zx61.Channels(); //通道数
- float alpha = 0.8f; //系数
- float beta = 60f; //增益
- for (int row = 0; row < height; row++)
- {
- for (int col = 0; col < width; col++)
- {
- if (cn == 1)
- {
- float color = zx61.At<float>(row, col);
- zx6161.Set<float>(row, col, color);
- }
- else if (cn == 3)
- {
- Vec3b color = new Vec3b
- {
- Item0 = SaturateCast((zx61.At<Vec3b>(row, col).Item0) * alpha + beta), //B
- Item1 = SaturateCast((zx61.At<Vec3b>(row, col).Item1) * alpha + beta), //G
- Item2 = SaturateCast((zx61.At<Vec3b>(row, col).Item2) * alpha + beta) //R
- };
- //Vec3f color = new Vec3f
- //{
- // Item0 = SaturateCast((zx61.At<Vec3f>(row, col).Item0) * alpha + beta), //B
- // Item1 = SaturateCast((zx61.At<Vec3f>(row, col).Item1) * alpha + beta), //G
- // Item2 = SaturateCast((zx61.At<Vec3f>(row, col).Item2) * alpha + beta) //R
- //};
- zx6161.Set<Vec3b>(row, col, color);
- }
- }
- }
- using (new Window("zx6161", WindowMode.AutoSize, zx6161))
- using (new Window("zx61", WindowMode.AutoSize, zx61))
- {
- Cv2.WaitKey();
- }
- }
- }
- /// <summary>
- /// 转换成byte类型
- /// </summary>
- /// <param name="value"></param>
- /// <returns></returns>
- private static byte SaturateCast(double value)
- {
- var rounded = Math.Round(value, 0);
- if (rounded < byte.MinValue)
- {
- return byte.MinValue;
- }
- if (rounded > byte.MaxValue)
- {
- return byte.MaxValue;
- }
- return (byte)rounded;
- }
复制代码
修改系数 和增益值 float alpha = 0.8f; float beta = 60f;
修改系数 和增益值 float alpha = 1.2f; float beta = 80f;
三次运行结果对比:
不懂公式莫要慌,记得代码也简单.懂了公式莫激动,学习之旅还很长.........
有缘lesson06见.......
本套学习心得,虽不是什么高瞻远瞩,但依旧禁止任何形式的转载or复制(含非商业),如需任何形式的转载or复制,还请论坛留言通知我一下下....
|
评分
-
参与人数 1 | 好评 +1 |
精币 +66 |
收起
理由
|
老郭
| + 1 |
+ 66 |
感谢发布原创作品,精易因你更精彩! |
查看全部评分
|