c++版opencv基础学习Day1_图像基础、图像变换及滤波基础

读取图片or读取视频

//读取图片
cv::Mat src = imread("你的图片的绝对路径");
//显示图片
cv::imshow("窗口名字",src);
//等待
cv::waitKey();//输入数字,则等待数字对应的毫秒数,不输入或输入为0则默认一直等待到按键
//读取视频
cv::Mat pic;
cv::VideoCapture capture;
capture.open("视频地址");
capture>>pic;
//这样就可以获取视频的第一帧了
int totalFrames=capture.get(cv::CAP_PROP_FRAME_COUNT);
//这个函数可以获得视频的总帧数
int currentFrames=0;
while(1){
   capture>>pic;
   if(currentFrames==totalFrames-1){
      current.set(cv::CAP_PROP_POS_FRAMES,0);
    }
    cv::imshow("result",pic);
    currentFrames++;
}
//以上可以一帧一帧看视频,并且可以实现视频循环播放

有关窗口

//创建新窗口
	namedWindow("newWindow", 1);
	//移动指定窗口到x、y位置
	moveWindow("newWindow", 1000, 1000);
	//改变指定窗口大小
	resizeWindow("newWindow", 900, 1000);
	//等待
	waitKey();
	//销毁指定窗口
	destroyWindow("newWindow");
	//销毁所有窗口
	destroyAllWindows();

cvtColor

函数说明:void cv::cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 )
输入参数:
				src				输入图像:8位无符号、16位无符号(CV_16UC…)或单精度浮点。
				dst				输出与src大小和深度相同的图像。
				dstCn			输出图像的通道数,默认0。如果参数为0,那么通道的数量将自动从src和code中导出。
				code			颜色空间转换码。总计有200种左右,只列出其中常用转换码。
						cv::ColorConversionCodes {
								cv::COLOR_BGR2RGB = 4,
								cv::COLOR_RGB2BGR = COLOR_BGR2RGB,
								cv::COLOR_BGR2GRAY = 6,
								cv::COLOR_RGB2GRAY = 7,
								cv::COLOR_GRAY2BGR = 8,
								cv::COLOR_GRAY2RGB = COLOR_GRAY2BGR
								}
备注1:若设置dst==src,即实现原图的转换。但不改变原矩阵,而是将src.data存放在编译器新建的内存地址中。
	Mat src = imread("D:/系统默认/桌面/RM/sha.jpeg");
	Mat dstrgb;
	Mat dstgray;
	cvtColor(src, dstrgb, COLOR_BGR2RGB, 0);
	cvtColor(src, dstgray, COLOR_BGR2GRAY, 0);
	imshow("img", src);
	imshow("RGB", dstrgb);
	imshow("GRAY", dstgray);
	waitKey()

边缘填充

#include <opencv2/core.hpp>
函数说明:void cv::copyMakeBorder( InputArray src, OutputArray dst, int top, int bottom, int left, int right, int borderType, const Scalar &value = Scalar() );
输入参数:
				src					输入图像。
				dst					与src类型相同的输出图像,大小为size(src.cols+left+right, src.rows+top+bottom)。
				top					顶部像素
				bottom				底部像素
				left				左侧像素
				right				右侧像素。指定在源图像的每个方向上要外推的像素数。top=1,bottom=1,left=1,right=1意味着需要构建像素宽为1的边界。
				borderType 			边框类型(即边界填充方式)。其中,BORDER_TRANSPARENT不可用。
						cv::BORDER_CONSTANT = 0 			iiiiii|abcdefgh|iiiiiii			常量法。填充常数值
						cv::BORDER_REPLICATE = 1 			aaaaaa|abcdefgh|hhhhhhh			复制法。复制最边缘像素
						cv::BORDER_REFLECT  = 2 			fedcba|abcdefgh|hgfedcb			反射法。以两边为轴
						cv::BORDER_WRAP = 3 				cdefgh|abcdefgh|abcdefg			外包装法。
						cv::BORDER_REFLECT_101 = 4 			gfedcb|abcdefgh|gfedcba			反射法。以最边缘像素为轴
						cv::BORDER_TRANSPARENT = 5 			uvwxyz|abcdefgh|ijklmno
						cv::BORDER_REFLECT101 = 6 			same as BORDER_REFLECT_101
						cv::BORDER_DEFAULT = 7 				same as BORDER_REFLECT_101
						cv::BORDER_ISOLATED = 8 			do not look outside of ROI
				value = Scalar() 	如果borderType==Border_CONSTANT,则为边界值。

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

//using namespace std;
//using namespace cv;

int main(int argc, char* argv[])
{
	//(1)读取图像
	std::string img_path = "D:/系统默认/桌面/RM/sha.jpeg";
	cv::Mat src = cv::imread(img_path, 1);

	//(2)判断图像是否读取成功
	if (!src.data)
	{
		std::cout << "can't read image!" << std::endl;
		return -1;
	}

	//(3)边缘填充
	float border_width = 0.2;
	int top = (int)(border_width * src.rows);
	int bottom = (int)(border_width * src.rows);
	int left = (int)(border_width * src.cols);
	int right = (int)(border_width * src.cols);

	cv::RNG rng;
	cv::Mat img1, img2, img3, img4, img5, img6, img7, img8, img9;
	cv::Scalar color = cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));

	cv::copyMakeBorder(src, img1, top, bottom, left, right, cv::BORDER_CONSTANT, color);
	cv::copyMakeBorder(src, img2, top, bottom, left, right, cv::BORDER_REPLICATE, color);
	cv::copyMakeBorder(src, img3, top, bottom, left, right, cv::BORDER_REFLECT, color);
	cv::copyMakeBorder(src, img4, top, bottom, left, right, cv::BORDER_WRAP, color);
	cv::copyMakeBorder(src, img5, top, bottom, left, right, cv::BORDER_REFLECT_101, color);
	//cv::copyMakeBorder(src, img6, top, bottom, left, right, cv::BORDER_TRANSPARENT, color);		//不可用
	cv::copyMakeBorder(src, img7, top, bottom, left, right, cv::BORDER_REFLECT101, color);
	cv::copyMakeBorder(src, img8, top, bottom, left, right, cv::BORDER_DEFAULT, color);
	cv::copyMakeBorder(src, img9, top, bottom, left, right, cv::BORDER_ISOLATED, color);

	//(4)显示图像
	cv::imshow("src", src);
	cv::imshow("img1", img1);
	cv::imshow("img2", img2);
	cv::imshow("img3", img3);
	cv::imshow("img4", img4);
	cv::imshow("img5", img5);
	//cv::imshow("img6", img6);		//不可用
	cv::imshow("img7", img7);
	cv::imshow("img8", img8);
	cv::imshow("img9", img9);

	cv::waitKey(0);
	return 0;
}

图像变换

图像缩放

  • 若调整src与dst对齐:
    resize(src, dst, dst.size(), 0, 0, interpolation);
  • 若在输入图像的基础上进行等比例缩放:
    resize(src, dst, Size(), 0.5, 0.5, interpolation);
#include <opencv2/imgproc.hpp>
函数说明:void cv::resize( InputArray src, OutputArray dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR )
输入参数:
				src				输入图像:8位无符号、16位无符号(CV_16UC…)或单精度浮点。
				dst				输出图像;大小为dsize(当它为非零时)或根据src.size()、fx和fy计算的大小;dst的类型与src的类型相同。
				dsize			输出图像大小;dsize=None,则计算为:dsize = Size(round(fx*src.cols), round(fy*src.rows)),dsize或fx和fy都必须为非零。
				fx = 0			沿水平轴的缩放比例;当它等于0时,它被计算为:(double)dsize.width/src.cols
				fy = 0			沿垂直轴的缩放比例;当它等于0时,它被计算为:(double)dsize.height/src.rows
				interpolation = INTER_LINEAR	插值方法。
						cv::InterpolationFlags{
								cv::INTER_NEAREST			最近邻插值
								cv::INTER_LINEAR			双线性插值(默认)
								cv::INTER_CUBIC 			双三次插值
								cv::INTER_AREA 				使用像素面积关系进行重新采样。
								cv::INTER_LANCZOS4 			8x8邻域上的Lanczos插值
								cv::INTER_LINEAR_EXACT 		位精确双线性插值
								cv::INTER_NEAREST_EXACT		位精确最近邻插值。这将产生与PIL、scikit图像或Matlab中的最近邻方法相同的结果。
								cv::INTER_MAX 				插值代码掩码
								cv::WARP_FILL_OUTLIERS 		标志,填充所有目的地图像像素。如果其中一些对应于源图像中的异常值,则将其设置为零。
								cv::WARP_INVERSE_MAP 		标志,逆变换
								}

图像翻转

#include <opencv2/core.hpp>
函数说明:void cv::flip( InputArray src, OutputArray dst, int flipCode );
输入参数:
				src					输入数组。
				dst					输出数组。与src相同大小和类型。
				flipCode			翻转标志。
							11、0表示绕x轴翻转。
							22、正值(例如1)表示绕y轴翻转。
							33、负值(例如-1)意味着在两个轴上翻转。

图像旋转

#include <opencv2/imgproc.hpp>
函数说明:Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale );
输入参数:
				center				输入图像的旋转中心坐标。一般取图像的中心点,可自定义。
				angle				旋转角度(以度为单位)。正值表示逆时针旋转(坐标原点假定为左上角)。
				scale				各向比例尺度因子。

 计算仿射变换的2×3矩阵:

#include <opencv2/imgproc.hpp>
函数说明:Mat cv::getAffineTransform( const Point2f src[], const Point2f dst[] );
输入参数:
				src					输入图像中三角形的顶点坐标。
				dst					输出图像中对应三角形的顶点坐标。

 计算透视变换的3×3矩阵

#include <opencv2/imgproc.hpp>
函数说明:Mat cv::getPerspectiveTransform( InputArray src, InputArray dst, int solveMethod = DECOMP_LU );
输入参数:
				src					输入图像中四边形的顶点坐标。
				dst					输入图像中对应四边形的顶点坐标。
				solveMethod = DECOMP_LU			解决方法。
								cv::DECOMP_LU 			选择最优的元素进行高斯消除。
								DECOMP_SVD 				奇异值分解法。系统可以是过定义的,并且/或者矩阵src1可以是奇异的
								DECOMP_EIG 				特征值分解。矩阵src1必须是对称的
								DECOMP_CHOLESKY 		Cholesky LLT分解。矩阵src1必须是对称的并且是正定义的
								DECOMP_QR 				QR分解。系统可以是过定义的,并且/或者矩阵src1可以是奇异的
								DECOMP_NORMAL			虽然前面的所有标志都是互斥的,但这个标志可以与前面的任何标志一起使用;这意味着使用通用公式(src1转置*src1*dst=src1转置*src2),而不是原系统(src1⋅dst=src2)

仿射变换:cv::warpAffine()

仿射变换(Affine Transformation):二维坐标到二维坐标的变换,其本质上就是多种变换的叠加。包括:缩放、平移、旋转、反射。 仿射变换(Affine Transformation)原理及应用

仿射的含义:
(1)共线性:若几个点在一条线上(变换前),则变换后仍然在一条线上。
(2)平行性:若两条线平行(变换前),则(变换后)仍然平行。
(3)共线比例不变性:若两条线段成比例(变换前),则(变换后)比例不变。

由于仿射特性,变换后仍是平行四边形,故只需要非共线的三个点就能确定。三个坐标点没有固定顺序,但变换前后的矩阵必须是对应的。

#include <opencv2/imgproc.hpp>
函数说明:void cv::warpAffine( InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const Scalar &borderValue = Scalar() );
输入参数:
				(1)src				输入图像。
				(2)dst				输出图像。输出大小为dsize且类型与src相同的图像。
				(3)M					2×3变换矩阵。2x3是三角形的三个顶点[x, y]。仿射变换只需要三个点,三点即可确定一个平行四边形。
				(4)dsize				输出图像的大小。
				(5)flags = INTER_LINEAR			插值方法。
								cv::INTER_NEAREST			最近邻插值
								cv::INTER_LINEAR			双线性插值(默认)
								cv::INTER_CUBIC 			双三次插值
								cv::INTER_AREA 				使用像素面积关系进行重新采样。
								cv::INTER_LANCZOS4 			8x8邻域上的Lanczos插值
								cv::INTER_LINEAR_EXACT 		位精确双线性插值
								cv::INTER_NEAREST_EXACT		位精确最近邻插值。这将产生与PIL、scikit图像或Matlab中的最近邻方法相同的结果。
								cv::INTER_MAX 				插值代码掩码
								cv::WARP_FILL_OUTLIERS 		标志,填充所有目的地图像像素。如果其中一些对应于源图像中的异常值,则将其设置为零。
								cv::WARP_INVERSE_MAP 		标志,逆变换
						
				(6)borderMode = BORDER_CONSTANT		边界类型(即边界填充方式)。
								cv::BORDER_CONSTANT = 0 			iiiiii|abcdefgh|iiiiiii			常量法。填充常数值
								cv::BORDER_REPLICATE = 1 			aaaaaa|abcdefgh|hhhhhhh			复制法。复制最边缘像素
								cv::BORDER_REFLECT  = 2 			fedcba|abcdefgh|hgfedcb			反射法。以两边为轴
								cv::BORDER_WRAP = 3 				cdefgh|abcdefgh|abcdefg			外包装法。
								cv::BORDER_REFLECT_101 = 4 			gfedcb|abcdefgh|gfedcba			反射法。以最边缘像素为轴
								cv::BORDER_TRANSPARENT = 5 			uvwxyz|abcdefgh|ijklmno
								cv::BORDER_REFLECT101 = 6 			same as BORDER_REFLECT_101
								cv::BORDER_DEFAULT = 7 				same as BORDER_REFLECT_101
								cv::BORDER_ISOLATED = 8 			do not look outside of ROI
				(7)borderValue = Scalar()				边界值(在边界不变的情况下)。缺省值是0。

 透视变换

 透视变换(Perspective Transformation):将二维图片投影到三维平面上,然后再转换到二维坐标下,所以也称为投影映射(Projective Mapping)。透视变换包括了所有的仿射变换。
透视变换相比仿射变换更加灵活,变换后会产生一个新的四边形,但不一定是平行四边形,所以需要非共线的四个点才能确定。四个坐标点没有固定顺序,但变换前后的矩阵必须是对应的。OpenCV4 详解仿射变换和透视变换和C++实现

#include <opencv2/imgproc.hpp>
函数说明:
void cv::warpPerspective( InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const Scalar &borderValue = Scalar() );
输入参数:
				(1)src				输入图像。
				(2)dst				输出图像。输出大小为dsize且类型与src相同的图像。
				(3)M					3×3变换矩阵。
				(4)dsize				输出图像的大小。
				(5)flags = INTER_LINEAR			插值方法。
								cv::INTER_NEAREST			最近邻插值
								cv::INTER_LINEAR			双线性插值(默认)
								cv::INTER_CUBIC 			双三次插值
								cv::INTER_AREA 				使用像素面积关系进行重新采样。
								cv::INTER_LANCZOS4 			8x8邻域上的Lanczos插值
								cv::INTER_LINEAR_EXACT 		位精确双线性插值
								cv::INTER_NEAREST_EXACT		位精确最近邻插值。这将产生与PIL、scikit图像或Matlab中的最近邻方法相同的结果。
								cv::INTER_MAX 				插值代码掩码
								cv::WARP_FILL_OUTLIERS 		标志,填充所有目的地图像像素。如果其中一些对应于源图像中的异常值,则将其设置为零。
								cv::WARP_INVERSE_MAP 		标志,逆变换
						
				(6)borderMode = BORDER_CONSTANT		边界类型(即边界填充方式)。
								cv::BORDER_CONSTANT = 0 			iiiiii|abcdefgh|iiiiiii			常量法。填充常数值
								cv::BORDER_REPLICATE = 1 			aaaaaa|abcdefgh|hhhhhhh			复制法。复制最边缘像素
								cv::BORDER_REFLECT  = 2 			fedcba|abcdefgh|hgfedcb			反射法。以两边为轴
								cv::BORDER_WRAP = 3 				cdefgh|abcdefgh|abcdefg			外包装法。
								cv::BORDER_REFLECT_101 = 4 			gfedcb|abcdefgh|gfedcba			反射法。以最边缘像素为轴
								cv::BORDER_TRANSPARENT = 5 			uvwxyz|abcdefgh|ijklmno
								cv::BORDER_REFLECT101 = 6 			same as BORDER_REFLECT_101
								cv::BORDER_DEFAULT = 7 				same as BORDER_REFLECT_101
								cv::BORDER_ISOLATED = 8 			do not look outside of ROI
				(7)borderValue = Scalar()				边界值(在边界不变的情况下)。缺省值是0。

实例

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
	//(1)读取图像
	string img_path1 = "D:/系统默认/桌面/RM/sha.jpeg";
	string img_path2 = "D:/系统默认/桌面/RM/tou.jpeg";

	Mat src1 = imread(img_path1, 1);
	Mat src2 = imread(img_path2, 1);

	if (src1.empty() || src2.empty()) {
		cout << "can't read image!!" << endl;
		return -1;
	}

	if (src1.rows != src2.rows || src1.cols != src2.cols) {

		cout << "src1=" << src1.rows << ":" << src1.cols << endl;
		cout << "src2=" << src2.rows << ":" << src2.cols << endl;
		//把2的尺寸改成和1一样大小
		resize(src2, src2, src1.size(), 0, 0, INTER_LINEAR);
		//这个时候再来看尺寸
		cout << "src1=" << src1.rows << ":" << src1.cols << endl;
	 	cout << "src2=" << src2.rows << ":" << src2.cols << endl;
	}
	Mat resize_B, resize_S;
	resize(src1, resize_B, Size(0, 0), 1, 2, INTER_LINEAR);
	resize(src1, resize_S, Size(0, 0), 0.8,0.8, INTER_LINEAR); 
	cout << "resize_B=" << resize_B.rows << ":" << resize_B.cols << endl;
	cout << "resize_S=" << resize_S.rows << ":" << resize_S.cols << endl;
	imshow("src1", src1);
	imshow("src2", src2);
	imshow("resize_B", resize_B);
	imshow("resize_S", resize_S);

	//图像翻转
	Mat src_flip;
	flip(src1, src_flip, 0);
	imshow("flip", src_flip);


	//(6)图像旋转(封装函数)
	 //Mat src_rotate;
	 Mat rotatedst;
	 int angle = 45;
	 int width = src1.rows;
	 int height = src1.cols;
	 Mat Matrix = getRotationMatrix2D(Point2f(width / 2, height / 2), angle, 1.0);
	 double cos = abs(Matrix.at<double>(0, 0));
	 double sin = abs(Matrix.at<double>(0, 1));
	 int nw = cos * width + sin * height;
	 int nh = sin * width + cos * height;
	 Matrix.at<double>(0, 2) += (nw / 2 - width/2);
	 Matrix.at<double>(1, 2) += (nh / 2 - height / 2);
	 warpAffine(src1, rotatedst, Matrix, Size(nh, nw));
	  imshow("rotatedst", rotatedst);
	  
	 
	  /*//图像平移
	 Mat transdst;
	 int height = src1.cols;
	 int wight = src1.rows;
	 int tx = 20;
	 int ty = 50;

	 float warp_values[] = { 1.0,0.0,tx,0.0,1.0,ty };
	 Mat translation_matrix = Mat(2, 3, CV_32F, warp_values);
	 warpAffine(src1, transdst, translation_matrix, src1.size());
	 imshow("transdst", transdst);*/
	 
	 //仿射变换
	 Mat src_wrap;
	 Point2f src_xy[3];
	 Point2f dst_xy[3];
	 src_xy[0] = cv::Point2f(0, 0);									//计算输入图像的三点坐标
	 src_xy[1] = cv::Point2f(src1.cols - 1, 0);
	 src_xy[2] = cv::Point2f(0, src1.rows - 1);
	 dst_xy[0] = cv::Point2f(src1.cols * 0.0, src1.rows * 0.33);			//计算输入图像变换后对应的三点坐标
	 dst_xy[1] = cv::Point2f(src1.cols * 0.85, src1.rows * 0.25);
	 dst_xy[2] = cv::Point2f(src1.cols * 0.15, src1.rows * 0.7);
	 Mat warp_mat = getAffineTransform(src_xy, dst_xy);
	 warpAffine(src1, src_wrap, warp_mat, src1.size());
	 

	 //标记坐标点
	 Mat src_WW(src1);
	 for (int i = 0; i < 4; i++) {
		 circle(src_WW, src_xy[i], 2, Scalar(0, 0, 255), 2);
		 circle(src_wrap, dst_xy[i], 2, Scalar(0, 0, 255), 2);
	 }
	 imshow("src_WW", src_WW);

	 //透视变换
	 Mat src_Pers;
	 Point2f srcPoints[4] = { Point2f(0,0),Point2f(src1.cols - 1,0),Point2f(0,src1.rows - 1),Point2f(src1.cols - 1,src1.cols - 1) };
	 Point2f dstPoints[4] = { Point2f(0,0),Point2f(100,0),Point2f(0,100),Point(150,100) };
	 Mat Trans = getPerspectiveTransform(srcPoints, dstPoints);
	 warpPerspective(src1, src_Pers, Trans, Size(src1.cols, src1.rows));
	 Mat src1_PP(src1);
	 for (int i = 0; i < 4; i++) {
		 circle(src1_PP, srcPoints[i],2, Scalar(0, 0, 255), 2);
		 circle(src_Pers, dstPoints[i], 2, Scalar(0, 0, 255), 2);
	 }
	 imshow("src1_PP", src1_PP);


	 
	
	 
	 imshow("src_wrap", src_wrap);
	 imshow("src_Pers", src_Pers);
	 waitKey();
	return 0;
}

图像滤波

Mat src = imread("D:/系统默认/桌面/RM/dirtyRabbit.jpg", IMREAD_UNCHANGED);
	Mat dst1, dst2, dst3, dst4, dst5;
	blur(src, dst1, Size(3, 3));
	GaussianBlur(src, dst2, Size(3, 3), 3.0);
	medianBlur(src, dst3, 3);
	bilateralFilter(src, dst4, 20, 200, 10);
	Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
	filter2D(src, dst5, src.depth(),kernel);
	imshow("均值滤波", dst1);
	imshow("高斯滤波", dst2);
	imshow("中值滤波", dst3);
	imshow("双边滤波", dst4);
		imshow("不知道", dst5);
		waitKey();
	return 0;;

 参考文章链接:Opencv C++图像处理(全)_c++ opencv 图像处理-优快云博客

旋转平移还不会的话请看:Opencv 基础(四):使用OpenCV进行图像旋转和平移_opencv图像旋转-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值