当前位置:   article > 正文

OpenCV学习笔记_cv::imwrite

cv::imwrite

Lesson1:环境配置与搭建

  • 完成VS2017的安装
  • 完成OpenCV的安装
  • 完成环境的搭建

Lesson2:图片的读取和显示

代码解释

  • 引入opencv包:

    #include<opencv2\opencv.hpp>
    #include<iostream>
    
    • 1
    • 2
  • 读取的图片是以矩阵Mat形式保存的

    Mat src = imread("C:/Users/12396/Desktop/Picture/OpenCV/face2.jpg");
    
    • 1
  • imshow("input",src),,input是窗口名字,可以为任意名称,src是要读取的对象

  • waitKey(0)表示等待时间,以ms为计时单位,人眼低于三百ms无法分辨

  • destroyAllWindows()表示销毁以前的所有窗口

  • 当图片过大无法调整时,我们要新建一个可以任意调整的窗口:

    namedWindow("你的窗口名称",WINDOW_FREERATIO)imshow("你的窗口名称",读取对象)
    
    • 1
    • 2

    在这里插入图片描述

  • 加载一张灰度图像

    Mat src = imread("图片路径",IMREAD_GRAYSCALE);`
    
    • 1

    在这里插入图片描述

  • 使用src.empty()来检查是否读取到了图片

    if (src.empty())
    {
    	printf("Image is not load....\n");
    }
    else
    {
    	printf("Image load successfully!");
    }	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

完整代码

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	Mat src = imread("C:/Users/12396/Desktop/Picture/OpenCV/face2.jpg",IMREAD_GRAYSCALE);
	if (src.empty())
	{
		printf("Image is not load....\n");
	}
	else
	{
		printf("Image load successfully!");
	}
	namedWindow("显示图片", WINDOW_FREERATIO);
	imshow("显示图片", src);
	waitKey(0);
	destroyAllWindows();
	return 0;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Lesson 3:图片色彩转换与保存

预备知识

  • 色彩空间转换函数:cvColor

    • COLOR_BGR2GRAY = 6:彩色到灰度
    • COLOR_GRAY2BGR = 8:灰度到彩色
    • COLOR_BGR2HSV = 40:BGR到HSV
    • COLOR_HSV2BGR = 54:HSV到BGR
  • 图像保存:imwrite(第一个参数,第二个参数)

    • 第一个参数是保存路径:有时候要用双斜杠
    • 第二个参数是保存对象

新建一个头文件:

在这里插入图片描述
在头文件中定义名称空间、类、方法:

#pragma once
#include<opencv2/opencv.hpp>

using namespace cv;

class quickdemo 
{
public:
	void color_Space_Convert(Mat & image);
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

新建一个cpp文件编写新的方法

在新建的.cpp文件中编写图像色彩转换、图片保存的方法,最后在main.cpp中将其实例化调用

在这里插入图片描述
在新建的.cpp文件中,我们想要引用刚才新建的头文件,但是发现没有找到路径:
在这里插入图片描述
在解决方案中包含路径,右击解决方案,点击属性:
在这里插入图片描述

在这里插入图片描述

用双引号加入解压后课件的路径即可:
在这里插入图片描述

  • 需要注意的是路径要加双斜杠,其一定要在路径的最后加上将要保存图片的名称,我这里将其保存为hsv.png

    imwrite("F://opencv_Envir//opencv//hsv.png",hsv);
    
    • 1
  • 如果去掉hsv.png,将会报错,且内存溢出:

    imwrite("F://opencv_Envir//opencv",hsv);
    
    • 1

    在这里插入图片描述

  • 错误信息:

    0x00007FFEFF9B4F69 处(位于 opencv.exe 中)有未经处理的异常: Microsoft C++ 异常: cv::Exception,位于内存位置 0x0000005C97EFF2D0 处。

  • 正确的代码:

    #include "quickopencvdemo.h"
    
    void quickdemo::color_Space_Convert(Mat & image)
    {
    	Mat gray, hsv;
    	cvtColor(image, hsv, COLOR_BGR2HSV);
    	cvtColor(image, gray, COLOR_BGR2GRAY);
    	imshow("HSV", hsv);
    	imshow("Gray",gray);
    	imwrite("F://opencv_Envir//opencv//hsv.png",hsv);
    	imwrite("F://opencv_Envir//opencv//gray.png", gray);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

main.cpp显示三张图片并保存

#include<opencv2\opencv.hpp>
#include<iostream>
#include "quickopencvdemo.h"

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	Mat src = imread("C:/Users/12396/Desktop/Picture/OpenCV/face2.jpg");
	if (src.empty())
	{
		printf("Image is not load....\n");
	}
	else
	{
		printf("Image load successfully!");
	}
	namedWindow("显示图片", WINDOW_FREERATIO);
	imshow("显示图片", src);//显示第一张原色图片
	quickdemo qk;//将头文件中定义的类进行实例化,命名为qk,使用qk.方法引用其色彩转换和图片保存方法
	qk.color_Space_Convert(src);//引用方法,显示灰度和hsc图像并保存,所以马上将要显示三张图片并保存两种图片在F盘
	waitKey(0);
	destroyAllWindows();
	return 0;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

最后我们在指定盘下面找到了保存的两张图片:灰度和HSV的
在这里插入图片描述

注意事项

  • imread读取的图像是八位
  • imshow只能显示八位
  • R、G、B三个通道各是八位,还有一个透明通道也是八位
  • R、G、B三个通道三位读取的顺序是B、G、R
  • H(0-180)、S(0-255)、V(0-255):分别表示色相、饱和度、亮度

Lesson 4 :图像对象的创建与赋值

上节回顾

  • 在创建的头文件中引入opencv库,引入名称空间,定义public方法

    #pragma once
    #include<opencv2/opencv.hpp>//引入opencv库函数
    
    using namespace cv;//引入名称空间
    
    class quickdemo//定义一个新的类
    {
    public://定义全局方法
    	void color_Space_Convert(Mat & image);//定义一个色彩转换的方法
    	void mat_creation(Mat & image);//定义一个图像矩阵方法
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 在新建的.cpp文件对头文件中定义的类实例化,并编写方法以便于main.cpp引用。

Mat基本结构

在这里插入图片描述

克隆(clone)、复制(copy)、赋值(=)

  • 赋值(=):其中一个改变时,另外一个也改变

    m3 = Scalar(0,0,255);
    Mat m4 = m3;//赋值,其中一个改变,另一个也改变
    m4 = Scalar(255, 0, 0);
    imshow("m3", m3);
    imshow("m4", m4);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

  • 克隆(clone):对克隆后的值修改不会影响原来的值

    Mat m4 = m3.clone();
    m4 = Scalar(246, 0, 255);
    imshow("m3",m3);
    imshow("m4", m4);
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

  • 复制copy:对复制后的值修改不影响原来的值

    Mat m4;
    m3.copyTo(m4);
    m4 = Scalar(65, 255, 90);
    imshow("m3",m3);
    imshow("m4", m4);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

创建空白图像

  • 先创建变量:

    Mat m3 = Mat::zeros(Size(8,8),CV_8UC1)
    • 1
    • Mat::zeros()表示创建全是0的矩阵
    • Size(8,8)表示矩阵大小
    • CV_8UC1中的8表示8位,UC表示无符号,1表示单个通道,也可以为三个
  • 方法中可以没有需要传入的参数:

    void mat_creation(不传入参数);//定义一个图像矩阵方法,括号里面为需要传入的参数,也可以没有
    
    • 1
  • 接着在main.cpp中实例化第二个类:

    quickdemo qk2;
    
    • 1
  • 调用方法
    在main.cpp中调用该方法,此时没有传入图片作为参数

    qk2.mat_creation();
    
    • 1
  • 如果想要传入图片作为参数,要重新定义方法:要在头文件,方法文件,main.cpp都更改为

    mat_creation(Mat & image);
    
    • 1
  • 打印输出:

    std::cout<<......<<std::endl;
    
    • 1
  • 图像宽度:

    m3.width;
    
    • 1
  • 图像高度:

    m3.height;
    
    • 1
  • 图像通道数:此时要加括号

    m3.channels();
    
    • 1
  • 打印一个通道:

    Mat m3 = Mat::zeros(Size(8, 8), CV_8UC1);//CV_8UC1表示8位,U表示无符号,1表示一个通道
    
    • 1

    在这里插入图片描述

  • 打印三个通道:将其改为CV_8UC3即可

    在这里插入图片描述

  • 第一个通道赋值为127:

    m3 = 127;//设置一个第一个通道为127
    
    • 1

    在这里插入图片描述

  • 使用scalar()函数将三个通道都赋值:此时显示红色,因为通道数显示顺序为B、G、R

    namedWindow("通道检验", WINDOW_FREERATIO);
    imshow("通道检验", m3);
    
    • 1
    • 2

    在这里插入图片描述
    在这里插入图片描述

Lesson 5 :图像像素的读写操作

文件创建

  • 在头文件中新定义一个全局方法:

    void pixel_visit_demo(Mat & image);
    
    • 1
  • quickdemo.cpp中编写该方法

    void quickdemo::pixel_visit_demo(Mat & image)
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
  • main.cpp中创建一个实例化的类,引用该方法

    quickdemo qk3;
    qk3.pixel_visit_demo(Mat & image);
    
    • 1
    • 2

基本知识

  • 可以调整的窗口

    namedWindow("使用数组修改像素值", WINDOW_FREERATIO);
    
    • 1
  • 获取图像像素的宽

    int w = image.cols;
    
    • 1
  • 获取图像像素的高

    int h = image.rows;
    
    • 1
  • 获取图像的通道数

    int c = image.channels();
    
    • 1
  • 灰度图像通道数为1,像素的数据类型为uchar,将其转化成int类型

    int pv = image.at<uchar>(row,col);
    
    • 1
  • 彩色图像通道数为3,像素的数据类型为Vec3b

    Vec3b bgr = image.at<Vec3b>(row,col);
    
    • 1

数组遍历

  • 假如为灰度图像,通道数为1,则获取像素值后直接修改即可

    int pv = image.at<uchar>(row,col);
    image.at<uchar>(row,col) = 255 - pv;
    
    • 1
    • 2
  • 假如图像为彩色图像,要用数组对每个通道的值进行修改

    Vec3b bgr = image.at<Vec3b>(row,col);
    image.at<Vec3b>(row,col)[0] = 255 - bgr[0];
    image.at<Vec3b>(row,col)[1] = 255 - bgr[1];
    image.at<Vec3b>(row,col)[2] = 255 - bgr[2];
    
    • 1
    • 2
    • 3
    • 4
  • 头文件

    void pixel_visit_demo_array(Mat & image);//Lesson 5:像素读写操作(使用数组)
    
    • 1
  • quickdemo.cpp

    //Lesson 5:像素读写操作(使用数组)
    void quickdemo::pixel_visit_demo_array(Mat & image)
    {
    	int w = image.cols;//获取图像的宽
    	int h = image.rows;//获取图像的高
    	int c = image.channels();//获取图像的通道数
    	imshow("原始图片", image);//显示原始图片
    	for (int row = 0; row < h; row++)
    	{
    		for (int col = 0; col < w; col++)
    		{
    			if (c == 1)//通道数为1,灰度图像
    			{
    				int pv = image.at<uchar>(row, col);//获取像素点的值并转化为int类型
    				image.at<uchar>(row, col) = 255 - pv;//对单通道的像素值进行修改
    			}
    			if (c == 3)//彩色图像,通道数为3
    			{
    				Vec3b bgr = image.at<Vec3b>(row, col);//bgr是一个数组
    				image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
    				image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
    				image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
    			}
    		}
    	}
    	imshow("使用数组修改像素值", image);//显示用数组修改后的图片
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • main.cpp

    //Lesson 5:图像像素的操作(指针或者数组)
    	quickdemo qk3;//将类实例化
    	qk3.pixel_visit_demo_array(src);//引用方法并传入读取的照片
    
    • 1
    • 2
    • 3
  • 原图:
    在这里插入图片描述

  • 数组遍历修改

    在这里插入图片描述

指针方式遍历

  • 定义一个指针uchar类型,先遍历行再遍历列,挨个移动

  • 头文件中定义新的方法

    void pixel_visit_demo_pointer(Mat & image);//Lesson 5:像素读写操作(使用指针)
    
    • 1
  • quickdemo.cpp中编写该方法

    //Lesson 5:像素读写操作(使用指针)
    void quickdemo::pixel_visit_demo_pointer(Mat & image)
    {
    	int w = image.cols;
    	int h = image.rows;
    	int c = image.channels();
    	for (int row = 0; row < h; row++)
    	{
    		uchar* current_row = image.ptr<uchar>(row);//定义一个指针,uchar类型
    		for (int col = 0; col < w; col++)
    		{
    			if (c == 1)//灰度图像
    			{
    				int pv = *current_row;
    				*current_row++ = 255 - pv;//挨个往下移动
    			}
    			if (c == 3)//彩色图像
    			{
    				*current_row++ = 255 - *current_row;
    				*current_row++ = 255 - *current_row;
    				*current_row++ = 255 - *current_row;
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • main.cpp中引用

    //Lesson 5:图像像素的操作(指针或者数组)
    	quickdemo qk3;//将类实例化
    	qk3.pixel_visit_demo_array(src);//引用方法并传入读取的照片
    
    • 1
    • 2
    • 3

Lesson 6:图像像素的算术操作

注意

  • 对两张图片进行算术运算要保证大小和类型相同

    Mat dst;
    Mat m = Mat::zeros(image.size(), image.type());
    
    • 1
    • 2
  • saturate_cast<数据类型>(判断内容):用来判断有没有溢出,超过则为范围的最大值,类似饱和函数

加法

  • 简单的加法-----使用标量函数

    Mat dst;
    dst = image + Scalar(50, 50, 50);
    imshow("原图", image);
    imshow("简单加法",dst);
    
    • 1
    • 2
    • 3
    • 4
  • 使用加法函数add

    • add(输入1,输入2,输出)

      //加法,使用add函数
      Mat dst;
      Mat m = Mat::zeros(image.size(), image.type());
      m = Scalar(20, 200, 200);
      add(image, m, dst);
      imshow("原图", image);
      imshow("乘法",dst);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 原图
      在这里插入图片描述

    • 加后的图
      在这里插入图片描述

  • 加法原理

    • 像素值分通道相加

      //加法原理
      Mat dst = Mat::zeros(image.size(), image.type());//输出图像
      Mat m = Mat::zeros(image.size(), image.type());
      m = Scalar(200, 200, 200);
      int w = image.cols;
      int h = image.rows;
      int c = image.channels();
      for (int row = 0; row < h; row++)
      {
      	for (int col = 0; col < w; col++)
      	{
      		Vec3b p1 = image.at<Vec3b>(row, col);//读取输入1的像素值
      		Vec3b p2 = m.at<Vec3b>(row, col);//读取m的像素值
      		dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);
      		dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);
      		dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);
      	}
      }
      imshow("原图", image);
      imshow("加法原理",dst);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    • 效果 在这里插入图片描述
      在这里插入图片描述

减法

  • 简单的减法----使用标量函数

    //减法,使用标量函数
    Mat dst;
    Mat m = Mat::zeros(image.size(), image.type());
    m = Scalar(100, 100, 100);
    dst = image - m;
    imshow("原图", image);
    imshow("乘法",dst);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 使用subtract函数

    • subtract(输入1,输入2,输出)

      	//减法,使用库函数
      	Mat dst;
      	Mat m = Mat::zeros(image.size(), image.type());
      	m = Scalar(100, 100, 100);
      	subtract(image, m, dst);
      	imshow("原图", image);
      	imshow("乘法",dst);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 原图 在这里插入图片描述

    • 减后的图
      在这里插入图片描述

乘法

  • 简单的乘法(容易报错)----使用标量函数:要注意A(m,n)必须要乘以B(n,m)

  • 使用multiply函数

    Mat dst;//创建一个图像
    Mat m = Mat::zeros(image.size(),image.type());//像素初值赋为0
    m = Scalar(2,2,2);//使用标量函数赋值为2
    multiply(image,m,dst);//输入的image和m相乘输出到dst中
    
    • 1
    • 2
    • 3
    • 4
  • 原图
    在这里插入图片描述

  • 乘后的图
    在这里插入图片描述

除法

  • 简单的除法----使用标量函数

    //除法,使用标量函数
    Mat dst;
    Mat m = Mat::zeros(image.size(), image.type());
    m = Scalar(20, 200, 2);
    dst = image/m;
    imshow("原图", image);
    imshow("乘法",dst);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 使用divide函数

    • divide(输入1,输入2,输出)

      //除法,使用divide函数
      Mat dst;
      Mat m = Mat::zeros(image.size(), image.type());
      m = Scalar(20, 200, 2);
      divide(image, m, dst);
      imshow("原图", image);
      imshow("乘法",dst);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 原图
      在这里插入图片描述

    • 除后的图
      在这里插入图片描述

Lesson 7:一个调节亮度的滚动条

头文件

void tracking_bar_demo(Mat & image);//Lesson 7:调节亮度的滚动条
  • 1

quickdemo.cpp

  • 需要注意的是这里的变量是全局的

    Mat src, dst, m;
    int lightness = 50;
    static void on_track(int , void*)
    {
    	m = Scalar(lightness, lightness, lightness);
    	add(src, m, dst);
    	imshow("亮度调整",dst);
    }
    void quickdemo::tracking_bar_demo(Mat & image)
    {
    
    	namedWindow("调整亮度",WINDOW_AUTOSIZE);
    	dst = Mat::zeros(image.size(), image.type());
    	m = Mat::zeros(image.size(), image.type());
    	src = image;
    	int max_value = 100;
    
    	createTrackbar("Value Bar", "调整亮度", &lightness, max_value, on_track);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

main.cpp中创建实例并调用

//Lesson 7:滚动条调整亮度
	quickdemo qk5;
	qk5.tracking_bar_demo(src);
  • 1
  • 2
  • 3

效果

在这里插入图片描述
在这里插入图片描述

Lesson 8:传递参数创建滚动条

static void on_lightness(int b, void* userdata)
{
	Mat image = *((Mat*)userdata);
	Mat dst = Mat::zeros(image.size(), image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	addWeighted(image, 1.0, m, 0, b, dst);
	imshow("亮度与对比度",dst);
}
static void on_contrast(int b, void* userdata)
{
	Mat image = *((Mat*)userdata);
	Mat dst = Mat::zeros(image.size(), image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	double contrast = b / 100.0;
	addWeighted(image,contrast,m,0.0,b,dst);
	imshow("亮度与对比度", dst);
}
void quickdemo::tracking_bar_demo(Mat & image)
{

	namedWindow("调整亮度",WINDOW_AUTOSIZE);
	int lightness = 50;
	int max_value = 100;
	int contrast_value = 100;
	createTrackbar("Value Bar", "调整亮度与对比度", &lightness, max_value, on_lightness,(&image));
	createTrackbar("Contrast Bar", "调整亮度与对比度", &contrast_value, 200, on_contrast,(&image));
	on_lightness(50, &image);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

Lesson 8:键盘响应

原理说明

  • 按1输出灰度值

    在这里插入图片描述
    在这里插入图片描述

  • 按2输出HSV图像

    在这里插入图片描述
    在这里插入图片描述

  • 按3像素相加

    在这里插入图片描述
    在这里插入图片描述

  • ESC退出

    在这里插入图片描述

代码

  • 等待键盘输入:waitKey(时间),以ms为单位
  • 输入转化为ASCII码保存
  • 通过判断数字及字母对应的ASCII码来执行相应的程序
void quickdemo::key_demo(Mat & image)
{
	Mat dst = Mat::zeros(image.size(), image.type());
	imshow("原图",image);
	while (true)
	{
		int c = waitKey(100);//等待键盘输入转化成ASCII码
		if (c == 27)
		{
			std::cout << "退出循环" << std::endl;
			break;//ESC键,退出循环
		}
		if (c == 49)//对应键盘值1
		{
			std::cout << "输入的是1" << std::endl;
			cvtColor(image, dst, COLOR_BGR2GRAY);//转为灰度图像
		}
		if (c == 50)//对应键盘值2
		{
			std::cout << "输入的是2" << std::endl;
			cvtColor(image, dst, COLOR_BGR2HSV);//转为HSV图像
		}
		if (c == 51)//对应键盘值3
		{
			std::cout << "输入的是3" << std::endl;
			dst = Scalar(50,50,50);
			add(image, dst,dst);//图片相加
		}
		imshow("键盘显示", dst);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

Lesson 9:颜色表

颜色表数组:

int colormap[] = 
{
		COLORMAP_AUTUMN,
		COLORMAP_BONE,
		COLORMAP_JET,
		COLORMAP_WINTER,
		COLORMAP_RAINBOW,
		COLORMAP_OCEAN,
		COLORMAP_SUMMER,
		COLORMAP_SPRING,
		COLORMAP_COOL,
		COLORMAP_PINK,
		COLORMAP_HOT,
		COLORMAP_PARULA,
		COLORMAP_MAGMA,
		COLORMAP_INFERNO,
		COLORMAP_PLASMA,
		COLORMAP_VIRIDIS,
		COLORMAP_CIVIDIS,
		COLORMAP_TWILIGHT,
		COLORMAP_TWILIGHT_SHIFTED
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

quickdemo.cpp

  • index++不断进行转换

    applyColorMap(image, dst, colormap[index]);	
    index++;
    
    • 1
    • 2
  • 但色彩数组里面只有18个数据,index不能一直加,与19取模可以将其限制在0-18

    applyColorMap(image, dst, colormap[index%19]);
    
    • 1
void quickdemo::color_table(Mat & image)
{
	int colormap[] = {
		COLORMAP_AUTUMN,
		COLORMAP_BONE,
		COLORMAP_JET,
		COLORMAP_WINTER,
		COLORMAP_RAINBOW,
		COLORMAP_OCEAN,
		COLORMAP_SUMMER,
		COLORMAP_SPRING,
		COLORMAP_COOL,
		COLORMAP_PINK,
		COLORMAP_HOT,
		COLORMAP_PARULA,
		COLORMAP_MAGMA,
		COLORMAP_INFERNO,
		COLORMAP_PLASMA,
		COLORMAP_VIRIDIS,
		COLORMAP_CIVIDIS,
		COLORMAP_TWILIGHT,
		COLORMAP_TWILIGHT_SHIFTED
	};
	Mat dst;
	int index = 0;
	while (true)
	{
		int c = waitKey(200);//等待输入
		if (c == 27)
		{
			break;//ESC退出
		}
		applyColorMap(image, dst, colormap[index]);
		index++;
		imshow("不断色彩转换", dst);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

效果:色彩不断变换

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Lesson 10:位操作

创建两幅图像并画矩形

Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);
rectangle(m1, Rect(100, 100,80,80), Scalar(255, 255, 0), -1, LINE_8, 0);
rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

在这里插入图片描述

位操作

  • bitwise_and(输入1,输入2,输出)

在这里插入图片描述

  • bitwise_or(输入1,输入2,输出)

在这里插入图片描述

  • bitwise_not(输入,输出)

    在这里插入图片描述
    在这里插入图片描述

  • bitwise_xor(输入1,输入2,输出)

    在这里插入图片描述

Lesson 11:通道分离与混合

split通道分离

  • 原理

在这里插入图片描述

  • 创建一个容器

    std::vector<Mat>mv;//创建一个容器
    
    • 1
    void quickdemo::channels_demo(Mat & image)
    {
    		//split通道分离
    	std::vector<Mat>mv;//创建一个容器
    	split(image, mv);//分离通道
    	imshow("通道分离0", mv[0]);
    	imshow("通道分离1", mv[1]);
    	imshow("通道分离2", mv[2]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

merge通道合并

		//merge通道合并
Mat dst;
mv[0] = 128;
mv[1] = 50;
merge(mv,dst);
imshow("通道合并",dst);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

通道混合

  • mixchannels(输入,个数,输出,个数,从哪到哪,通道数)

  • 定义通道流向:1到2,1到1等…

    int from_to[] = {0,2,1,1,2,0};
    
    • 1

    在这里插入图片描述

Lesson 12:图像色彩空间转化

  • 原图

    在这里插入图片描述

  • 色彩空间转换:BGR----HSV

    //色彩空间转换
    Mat hsv;
    cvtColor(image, hsv, COLOR_BGR2HSV);
    
    • 1
    • 2
    • 3
  • 提取轮廓

    在这里插入图片描述
    在这里插入图片描述

    //过滤
    Mat masker;
    inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), masker);//过滤掉HSV图像中的某个通道,最大值最小值
    imshow("makser",masker);
    
    • 1
    • 2
    • 3
    • 4
  • 将提取的轮廓像素取反

    bitwise_not(masker,masker);//对提取的轮廓取反
    
    • 1

    在这里插入图片描述

  • 粘贴到红色背景的图上

    image.copyTo(redback, masker);
    
    • 1

    在这里插入图片描述

Lesson 13:图像像素值统计

单个通道的最大值和最小值

  • 定义最大值最小值:double类型
  • 定义最大值最小值位置:Point类型
  • 分离通道
  • 循环检测每个通道的最大值和最小值
double mixv, maxv;//定义像素的最大值和最小值
Point minLoc, maxLoc;//定义像素的最大最小值位置
std::vector<Mat>mv;//定义一个容器,分离通道,因为只有单通道才能统计
split(image, mv);
for (int i = 0; i < mv.size(); i++)
{
	minMaxLoc(mv[i], &mixv, &maxv, &minLoc, &maxLoc, Mat());
	std::cout << "通道:" << i <<std:: endl;
	std::cout << "mixv:" << mixv << "maxv:" << maxv << std::endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

均值和方差(deviation)

  • 均值和方差是矩阵类型

  • menaStdDev(输入图像,均值,方差)

    Mat mean, stddev;//定义均值和方差
    meanStdDev(image,mean,stddev);
    
    • 1
    • 2

    在这里插入图片描述

Lesson 14:图像几何形状绘制

  • 像素坐标系在一张图像的左上角位置

矩形

  • 矩形变量:Rect r
  • 矩形的位置:r.x r.y
  • 矩形的大小:r.width r.height
  • 绘制矩形的命令:rectangle(输入图像,矩形参数,矩形的颜色Scalar(),线条粗细(-1表示填充),8,0)
    //绘制矩形
    Rect r;
    r.x = 100;
    r.y = 150;
    r.width = 100;
    r.height = 100;
    Mat dst = Mat::zeros(image.size(),image.type());
    rectangle(image,r,Scalar(255,0,255),2,8,0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

绘制圆

  • 绘制圆:circle(输入图像,圆心:Point(x,y),半径,颜色,线条粗细(-1表示填充),8(LINE_AA表示反锯齿),0)
    //绘制圆
    circle(image, Point(200, 25), 50, Scalar(0, 255, 200), 2, 8, 0);
    
    • 1
    • 2

绘制直线

  • 绘制直线:line(输入图像,Point(起始点),Point(终点),Scalar(),线条粗细(-1表示填充),8(LINE_AA表示反锯齿),0)

    //绘制直线
    line(image, Point(20, 50), Point(100, 200), Scalar(30, 25, 60), 2, 8, 0);
    
    • 1
    • 2

绘制椭圆

  • 椭圆变量:RotatedRect e

  • 椭圆位置:e.center = Point(x,y)

  • 椭圆大小:e.size = Size(m,n)

  • 椭圆角度:e.angle = 90

  • 绘制椭圆命令:ellipse(输入图像,椭圆参数,Scalar(),线条粗细(-1表示填充),8(LINE_AA表示反锯齿),0)

    //绘制椭圆
    RotatedRect e;
    e.center = Point(60,50);
    e.size = Size(20, 60);
    e.angle = 90;
    ellipse(image, e, Scalar(46, 97, 255), 2, 8);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

图像合并

  • 图像合并:addWeighted(输入1,权重1,输入2,权重2,0,输出)

    //合并两张图像
    Mat dst2;
    addWeighted(image, 0.7, dst, 0.3, 0, dst2);
    imshow("几何图形",dst2);
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

Lesson 15:随机绘图演示

流程

  • 创建一张三通道的空白图像

    Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
    
    • 1
  • 求取该图像的长宽

    int w = canvas.cols;
    int h = canvas.rows;
    
    • 1
    • 2
  • 定义随机变量

    RNG rng(12345);
    
    • 1
  • 获取随机点

    int x1 = rng.uniform(0, w);
    int y1 = rng.uniform(0, h);
    int x2 = rng.uniform(0, w);
    int y2 = rng.uniform(0, h);
    
    • 1
    • 2
    • 3
    • 4
  • 获取随机颜色

    int b = rng.uniform(0, 255);
    int g = rng.uniform(0, 255);
    int r = rng.uniform(0, 255);
    
    • 1
    • 2
    • 3
  • 绘制直线

    line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, LINE_AA, 0);
    
    • 1

完整代码

void quickdemo::randow_demo()
{
	Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
	int w = canvas.cols;
	int h = canvas.rows;
	RNG rng(12345);
	while (true)
	{
		int c = waitKey(10);
		if (c == 27)
		{
			break;
		}
		int x1 = rng.uniform(0, w);
		int y1 = rng.uniform(0, h);
		int x2 = rng.uniform(0, w);
		int y2 = rng.uniform(0, h);
		int b = rng.uniform(0, 255);
		int g = rng.uniform(0, 255);
		int r = rng.uniform(0, 255);
		line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, LINE_AA, 0);
		imshow("随机绘图演示",canvas);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

效果

在这里插入图片描述

Lesson 16:多边形的绘制与填充

准备知识

  • 创建一个空白画布

    Mat canvas = Mat::zeros(Size(512,512),CV_8UC3);
    
    • 1
  • 绘制多边形首先需要创建点

    Point p1(100, 100);
    Point p2(350, 100);
    Point p3(450, 280);
    Point p4(320, 450);
    Point p5(80, 400);
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 创建向量保存这些点

    std::vector<Point>pts;
    pts.push_back(p1);
    pts.push_back(p2);
    pts.push_back(p3);
    pts.push_back(p4);
    pts.push_back(p5);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 多边形绘制命令

    polylines(canvas, pts, true, Scalar(0, 0, 255), 2, 8, 0);
    
    • 1

    在这里插入图片描述

  • 绘制多边形要使用单独的填充函数,不能简单将参数改为-1

    fillPoly(canvas,pts,Scalar(255,0,255),8,0);
    
    • 1

    在这里插入图片描述

  • 还有一个绘制多边形的命令:drawContours(),要先创建一个点集

    std::vector<std::vector<Point>>contours;//也是创建一个点集
    contours.push_back(pts);
    drawContours(canvas, contours, -1, Scalar(255, 0, 255), 2);
    
    • 1
    • 2
    • 3

    在这里插入图片描述

Lesson 17:鼠标操作与响应

Lesson 18:图像像素类型转化与归一化

四种归一化方法

  • NORM_MINMAX
  • NORM_INF
  • NORM_L1
  • NORM_L2

最常用的是MINMAX方法

流程

  • 没有转化之前的数据类型

    Mat dst;
    std::cout << "原始像素类型:" << image.type() << std::endl;
    
    • 1
    • 2
  • 转化之后的像素类型

    std::cout << "转化之后像素类型:" << image.type() << std::endl;
    
    • 1
  • 像素归一化之前要转化成浮点类型

    image.convertTo(image, CV_32F);
    
    • 1
  • 归一化后的像素类型

    normalize(image, dst, 1, 0, NORM_MINMAX);
    std::cout << "归一化后的像素类型:" << dst.type() << std::endl;
    
    • 1
    • 2

    在这里插入图片描述

Lesson 19:图像放缩与插值

四种插值方法

  • INTER_NEAREST
  • INTER_LINEAR
  • INTER_CUBIC
  • INTER_LANCZOS4

图像放缩

  • 创建图像

    Mat large, small;
    
    • 1
  • 获取图像尺寸

    int w = image.cols;
    int h = image.rows;
    
    • 1
    • 2
  • 放大缩小:resize()

    resize(image, large, Size(w*1.5, h*1.5), 0, 0, INTER_LINEAR);//放大
    imshow("放大",large);
    resize(image, small, Size(w/1.5, h/1.5), 0, 0, INTER_LINEAR);//缩小
    imshow("缩小", small);
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

Lesson 20:图像翻转

  • flip(输入,输出,0):上下翻转

    flip(image, dst, 0);//上下翻转
    imshow("上下翻转",dst);
    
    • 1
    • 2

    在这里插入图片描述

  • flip(输入,输出,1):左右翻转

    flip(image, dst, 1);//左右翻转
    imshow("左右翻转", dst);
    
    • 1
    • 2

    在这里插入图片描述

  • flip(输入,输出,-1):对角线翻转

    flip(image, dst, -1);//对角线
    imshow("对角线翻转", dst);
    
    • 1
    • 2

    在这里插入图片描述

Lesson 21:图像旋转

步骤\

  • 求出原图像的宽高

  • 求出翻转矩阵M

    M = getRotationMatrix2D(Point2f(w / 2, h / 2), 45, 1.0);//第一个参数位图像中心,第二个为旋转角度,第三个为缩放系数
    
    • 1

    在这里插入图片描述

  • 求出旋转后图像的宽和高

    double cos = abs(M.at<double>(0, 0));//M矩阵的一行一列元素
    double sin = abs(M.at<double>(0, 1));//M矩阵的一行二列元素
    double nw = cos * w + sin * h;//新图像的宽
    double nh = sin * w + cos * h;//新图像的高
    M.at<double>(0, 2) += (nw / 2 - w / 2);
    M.at<double>(1, 2) += (nh / 2 - h / 2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

  • 旋转:旋转就是放射变换affine

    warpAffine(image, dst, M, Size(nw, nh), INTER_LINEAR, 0, Scalar(255, 0, 0));
    
    • 1

    在这里插入图片描述

Lesson 22:读取摄像头或者视频文件

基本原理

  • 创建一个视频类型的变量:为0表示调用摄像头,里面加上绝对路径可以调用视频文件

    VideoCapture capture(0);//为0则表示调用摄像头
    
    • 1
  • 创建一个图像变量:VideoCapture capture()

    Mat frame;
    
    • 1
  • 循环读取图片:在里面设置一些退出机制(按键检测,没有读取到图片等)

    while (true)
    {
    	capture.read(frame);
    	if (frame.empty())//没有读取到图像,退出
    	{
    		break;
    	}
    	int c = waitKey(10);//等待键盘输入
    	if (c == 27)//如果有ESC键按下,则退出
    	{
    		break;
    	}
    	imshow("摄像头", frame);//循环显示图像
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 释放摄像头资源:循环体外

    capture.release();//释放摄像头占用资源
    
    • 1

Lesson 23:视频文件的保存

步骤

  • 加载视频

    VideoCapture capture("F:/opencv_Envir/exercise/GitLab.mp4");//为0则表示调用摄像头
    
    • 1
  • 获取视频的分辨率(宽,高,帧数,fps)

    int w = capture.get(CAP_PROP_FRAME_WIDTH);
    int h = capture.get(CAP_PROP_FRAME_HEIGHT);
    int count = capture.get(CAP_PROP_FRAME_COUNT);
    double fps = capture.get(CAP_PROP_FPS);
    
    • 1
    • 2
    • 3
    • 4
  • 输出以上信息

    std::cout << "width:" << w << std::endl;
    std::cout << "height:" << h << std::endl;
    std::cout << "count:" << count << std::endl;
    std::cout << "fps:" << fps << std::endl;
    
    • 1
    • 2
    • 3
    • 4
  • 创建保存视频变量:VideoWriter writer(“路径”,视频编码信息,fps,Size(宽,高),true)

    VideoWriter writer("F:/opencv_Envir/exercise/test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(w, h), true);
    
    • 1
  • 视频编码信息自动获取:capture.get(CAP_PROP_FOURCC)

  • 读取视频文件

    Mat frame;
    while (true)
    {
    	capture.read(frame);
    	if (frame.empty())//没有读取到图像,退出
    	{
    		break;
    	}
    	int c = waitKey(10);//等待键盘输入
    	if (c == 27)//如果有ESC键按下,则退出
    	{
    		break;
    	}
    	imshow("摄像头", frame);//循环显示图像
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 释放资源

    capture.release();//释放摄像头占用资源
    writer.release();
    
    • 1
    • 2

效果

在这里插入图片描述

在这里插入图片描述

Lesson 24:图像直方图

步骤

  • 三通道分离

    std::vector<Mat>bgr_plane;
    split(image, bgr_plane);
    
    • 1
    • 2
  • 定义参数变量

    const int channels[1] = { 0 };
    const int bins[1] = { 256 };
    float hranges[2] = { 0,255 };
    const float* ranges[1] = {hranges};
    
    • 1
    • 2
    • 3
    • 4
  • 计算BGR三通道的直方图

    calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
    calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
    calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
    int hist_w = 512;
    int hist_h = 400;
    int bin_w = cvRound((double)hist_w/bins[0]);
    Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 归一化直方图数据

    normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
    normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
    normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
    
    • 1
    • 2
    • 3
  • 显示直方图

    for (int i = 1; i < bins[0]; i++)
    {
    line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),Point(bin_w*(i),hist_h-cvRound(b_hist.at<float>(i))),Scalar(255,0,0),2,8,0);
    line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))), Point(bin_w*(i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
    line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))), Point(bin_w*(i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);
    }
    namedWindow("Hisogram", WINDOW_AUTOSIZE);
    imshow("Hisogram",histImage);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

效果

在这里插入图片描述

Lesson 25:二维直方图

步骤

void quickdemo::histogram_2d_demo(Mat & image)
{
	Mat hsv, hs_hist;
	cvtColor(image, hsv, COLOR_BGR2HSV);
	int hbins = 30, sbins = 32;
	int hist_bins[] = {hbins,sbins};
	float h_range[] = { 0,180 };
	float s_range[] = { 0,256 };
	const float* hs_range[] = { h_range,s_range };
	int hs_channels[] = { 0,1 };
	calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_range, true, false);
	double maxVal = 0;
	minMaxLoc(hs_hist, 0, &maxVal, 0, 0);
	int scale = 10;
	Mat hist2d_image = Mat::zeros(sbins*scale, hbins*scale, CV_8UC3);
	for (int h = 0; h < hbins; h++)
	{
		
		for (int s = 0; s < sbins; s++)
		{
			float binVal = hs_hist.at<float>(h, s);
			int intensity = cvRound(binVal * 255 / maxVal);
			rectangle(hist2d_image, Point(h*scale, s*scale), Point((h + 1)*scale - 1, (s + 1)*scale - 1), Scalar::all(intensity), -1);
		}
	}
	applyColorMap(hist2d_image, hist2d_image, COLORMAP_JET);
	imshow("H-S histogram",hist2d_image);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

效果

在这里插入图片描述

Lesson 26:直方图均衡化

灰度图像

在这里插入图片描述

直方图均衡化

  • equalizeHist(gray, dst);

    void quickdemo::equalize_demo(Mat & image)
    {
    	Mat gray;
    	cvtColor(image, gray, COLOR_BGR2GRAY);
    	imshow("灰度图像", gray);
    	Mat dst;
    	equalizeHist(gray, dst);
    	imshow("直方图均衡化",dst);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

Lesson 27:图像卷积(blur)操作

原理

  • 原图像选定一个矩阵,每次矩阵按行移动

  • 选定一个矩阵作为窗口

  • 原图像每个元素乘以窗口矩阵的元素相加处于窗口元素的个数作为卷积输出

  • 原图像矩阵挨个移动

    在这里插入图片描述

步骤

  • Size()表示窗口大小

    Mat dst;
    blur(image, dst, Size(2, 2), Point(-1, -1));
    imshow("图像模糊",dst);
    
    • 1
    • 2
    • 3

效果

在这里插入图片描述

在这里插入图片描述

Lesson 28:高斯模糊

原理

  • 高斯模糊多了一个 σ \sigma σ作为参数

    GaussianBlur(image, dst, Size(10, 10), 15);
    
    • 1

    在这里插入图片描述

效果

在这里插入图片描述

在这里插入图片描述

Lesson 29:高斯双边模糊

代码

Mat dst;
bilateralFilter(image, dst, 0,100,10);
imshow("原图", image);
imshow("高斯模糊", dst);
  • 1
  • 2
  • 3
  • 4

效果

在这里插入图片描述

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/103604
推荐阅读
相关标签
  

闽ICP备14008679号