opencv入门

窗口显示

图片的显示

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main() 
{
	cv::Mat src = imread("C:/Users/26961/Desktop/dog.jpg");
	if (src.empty()) {
		cout << "图图片未加载" << endl;
		return -1;
	}
	imshow("输入窗口", src);
	waitKey(0); //阻塞式等待
	destroyAllWindows(); //销毁所有的窗口对象
	return 0;
}

并不能进行窗口的缩放,只是图片固定在创建的窗口上会固定尺寸

注意:

  • imread可以加载灰度图像
cv::Mat src = imread("C:/Users/26961/Desktop/dog.jpg", 
									IMREAD_GRAYSCALE);

显示效果:
在这里插入图片描述

namedWindow 可以进行窗口的缩放

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main() 
{
	cv::Mat src = imread("C:/Users/26961/Desktop/dog.jpg");
	if (src.empty()) {
		cout << "图片未加载" << endl;
		return -1;
	}
	
	//可以进行窗口的缩放
	namedWindow("输入窗口", WINDOW_FREERATIO);  //WINDOW_FREERATIO -可以调整图片的自由比率
	imshow("输入窗口", src);
	waitKey(0);//阻塞式等待
	destroyAllWindows();
	return 0;
}

图片色彩的转换

1.色彩空间转换函数- cvtColor

COLOR_ BGR2GRAY = 6彩色到灰度
COLOR_ _GRAY2BGR= 8灰度到彩色
COLOR_ BGR2HSV = 40 BGR到HSV
COLOR_ HSV2BGR = 54 HSV到BGR

2.图像保存- imwrite

  • 第一个参数是图像保存路径
  • 第二个参数是图像内存对象

hsv和GRAY

  • H 、S 、V三个通道的取值范围在0~180之间, H、S可以改变图片的色彩,V可以改变图片的亮度。
void QuickDemo::quick_space_demo(Mat& src)
{
	Mat gray, hsv;  //用于存储灰色和彩色的Mat对象

	
	cvtColor(src, hsv, COLOR_BGR2HSV);	//设置灰色
	cvtColor(src, gray, COLOR_BGR2GRAY); //设置彩色
	
	//调整图片的自由比率
	namedWindow("灰色", WINDOW_FREERATIO);
	namedWindow("hsv", WINDOW_FREERATIO);

	imshow("hsv", hsv);				//显示转换后的图片
	imshow("灰色", gray);			//显示转换后的图片

	//保存转换颜色后的图片
	imwrite("C:/Users/26961/Desktop/images/hsv.jpg", hsv);
	imwrite("C:/Users/26961/Desktop/images/gray.jpg", gray);
}

main.cpp

#include <opencv2/opencv.hpp>
#include <iostream>
#include "quick_demo.h"


using namespace cv;
using namespace std;

int main()		
{
	cv::Mat src = imread("C:\Users\26961\Desktop\images\dog.jpg");
	if (src.empty()) {
		cout << "图片未打开" << endl;
		return -1;
	}

	//可以进行窗口的缩放,图片与窗口大小匹配
	namedWindow("输入窗口", WINDOW_FREERATIO);
	imshow("输入窗口", src);

	//彩色转换
	QuickDemo obj;
	obj.quick_space_demo(src);  
	//将Mat 对象传递给quick_space_demo函数,将转换的图片保存到
	// C:/Users/26961/Desktop/images/路径中

	//阻塞等待
	waitKey(0);

	//销毁窗口对象
	destroyAllWindows();
	return 0;

}

在这里插入图片描述

openCV图像对象创建与赋值

图像对象的创建和赋值

void QuickDemo::mat_creater_demo(Mat& src) 
{
	Mat m1, m2;
	m1 = src.clone(); //赋值方式一
	src.copyTo(m2);   //赋值方式二
	cvtColor(src, m1, COLOR_BGR2HSV); //为了区别,将m1对象色彩设置为彩色

	imshow("m1对象", m1);
	imshow("m2对象", m2);
}

创建 8 * 8 的空白对象

//设置8 * 8的空白图像,指定一个通道。
Mat m3 = Mat::zeros(Size(8, 8), CV_8UC1);

/*
	显示宽度、高度、通道。
*/
std::cout << "width: " << m3.cols << " height: " << m3.rows  
 << " channels: " << m3.channels() << std::endl;

//打印空白图像
std::cout << m3 << std::endl;

在这里插入图片描述

使用ones和zeros的区别
如果在创建空白Mat对象时,如果指定要创建3个通道的时候,但是此时是使用Mat::ones该方法进行创建的话都出现1和0交替的现象,并且1总是出现在1通道

Mat m3 = Mat::ones(Size(8, 8), CV_8UC3);
std::cout << "width: " << m3.cols << " height: " << m3.rows  
 << " channels: " << m3.channels() << std::endl;

在这里插入图片描述

而如果是使用Mat::zeros方法时,并不会发送该情况,而是全部会初始化为0。

Mat m3 = Mat::zeros(Size(8, 8), CV_8UC3);

在这里插入图片描述

改变空白对象的色彩

Mat m3 = Mat::zeros(Size(500, 500), CV_8UC3);
m3 = Scalar(255,0,0); //设置m3对象的色彩,这里会被设置为纯蓝色
imshow("图像", m3);	  //显示m3对象			

Mat对象之间的深浅拷贝问题

void QuickDemo::mat_creater_demo(Mat& src) 
{
	Mat m1, m2;
	m1 = src.clone(); //赋值方式一
	src.copyTo(m2);   //赋值方式二
	cvtColor(src, m1, COLOR_BGR2HSV); //为了区别,将m1对象色彩设置为彩色

	/*imshow("m1对象", m1);
	imshow("m2对象", m2);*/

	Mat m3 = Mat::zeros(Size(500, 500), CV_8UC3);
	m3 = Scalar(255,0,0); //设置m3对象的色彩
	imshow("图像3", m3);
	std::cout << "width: " << m3.cols << " height: " << m3.rows  
	 << " channels: " << m3.channels() << std::endl;
		

	//浅拷贝
	Mat m4 = m3;
	m4 = Scalar(0, 0 ,0); //修改了m3
	imshow("图像4", m4);
	
	//深拷贝
	Mat m5 = m3.clone(); //深拷贝已经修改了的m3
	imshow("图像5", m5);
}

如果只是单纯的进行浅拷贝的话,那么m4对象的改变会影响到m3对象, 直到m4被修改了后m3也会收到影响。

在这里插入图片描述

解决的方案就是让m4深拷贝m3,那么就不会导致m3发生改变

void QuickDemo::mat_creater_demo(Mat& src) 
{
	Mat m3 = Mat::zeros(Size(500, 500), CV_8UC3);
	m3 = Scalar(255,0,0); //设置m3对象的色彩
	imshow("图像3", m3);
	std::cout << "width: " << m3.cols << " height: " << m3.rows  
	 << " channels: " << m3.channels() << std::endl;
		
	//浅拷贝
	Mat m4 = m3.clone();
	m4 = Scalar(0, 0 ,0);
	imshow("图像4", m4);
	
	//深拷贝
	Mat m5 = m3.clone();
	m5 = Scalar(160,20,20);
	imshow("图像5", m5);
}

效果:

在这里插入图片描述

opencv图像像素点读写操作

  • 数组遍历
void changeimg(Mat &src) {

	int w = src.cols;   //列
	int h = src.rows;	//行
	int dims = src.channels();  //通道

	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			if (dims == 1) { //单通道的灰度图像

				//获取[i, j]位置的像素值
				int pv = src.at<uchar>(i, j);
				//修改[i, j]位置的像素值
				src.at<uchar>(i, j) = 255 - pv;
			}

			//三个通道的像素点需要修改三次,因为三个通道的彩色图像每一个像素点可以存储3个值
			if (dims == 3) { //3通道的彩色图像
			
				//Vec3b 是一个三通道的像素点,所以Vec3b对象包含三个值 
				Vec3b bgr = src.at<Vec3b>(i, j);
				src.at<Vec3b>(i, j)[0] = 255 - bgr[0];
				src.at<Vec3b>(i, j)[1] = 255 - bgr[1];
				src.at<Vec3b>(i, j)[2] = 255 - bgr[2];
			}
		}
	}
	
}

void QuickDemo::pixel_vlist_demo(Mat& src) {
	Mat m1 = src.clone();
	changeimg(m1);
	imshow("src图像", src);


	Mat m2 = src.clone();
	changeimg(m2);
	imshow("m2图像", m2);
}

修改前 vs 修改后

在这里插入图片描述

  • 指针方式遍历
void changeimg2(Mat& src) {

	int w = src.cols;   //列
	int h = src.rows;	//行
	int dims = src.channels();  //通道

	for (int i = 0; i < h; i++) {
		// 获取行指针
		uchar* curr_row = src.ptr<uchar>(i);
		for (int j = 0; j < w; j++) {

			//获取列指针
			if (dims == 1) {
				int pv = *curr_row;
				*curr_row++ = 255 - pv;
			}
			if (dims == 3) {
				//遍历一个像素点拥有三个值的图像
				*curr_row++ = 255 - *curr_row;
				*curr_row++ = 255 - *curr_row;
				*curr_row++ = 255 - *curr_row;
			}
		}
	}

}

void QuickDemo::pixel_vlist_demo(Mat& src) {
	Mat m1 = src.clone();
	changeimg1(m1);
	imshow("src图像", m1);


	Mat m2 = src.clone();
	changeimg2(m2);
	imshow("m2图像", m2);
}

图像像素的算术操作

除法操作两种方式

void QuickDemo::operator_demo(Mat& src)
{
	Mat dst;
	dst = src / Scalar(2, 2, 2);

	imshow("算术操作", dst);
}

void QuickDemo::operator_demo(Mat& src)
{
	Mat dst;
	Mat m = Mat::zeros(src.size(), src.type());
	m = Scalar(2, 2, 2);

	divide(src, m, dst);
	imshow("除法操作", dst);
}

乘法操作

void QuickDemo::operator_demo(Mat& src)
{
	Mat dst;
	Mat m = Mat::zeros(src.size(), src.type());
	m = Scalar(2, 2, 2);

	multiply(src, m, dst); //src 与 m相乘的结果放入dst中
	imshow("算术操作", dst);
}

像素点相加

void QuickDemo::operator_demo(Mat& src)
{
	//初始化dst, 用于存储m和src 运算后的结果值 
	Mat dst = Mat::zeros(src.size(), src.type());
	//初始化m对象
	Mat m = Mat::zeros(src.size(), src.type());
	m = Scalar(2, 2, 2);

	

	int h = src.rows; //获取行
	int w = src.cols; //获取列
	
	//计算 m对象和src的和值
	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			Vec3b p1 = src.at<Vec3b>(i, j);
			Vec3b p2 = m.at<Vec3b>(i, j);
			dst.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(p1[0] + p2[0]);
			dst.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(p1[1] + p2[1]);
			dst.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(p1[2] + p2[2]);
		}
	}

	imshow("算术操作", dst);
	
}

算术运算常用的四个接口

//加法
void add(src, m, dst);
//减法
void subtract(src, m, dst);
//乘法
void multiply(src, m, dst);
//除法
void divide(src, m, dst);

在这里插入图片描述

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>