opencv基本的图像处理

文章目录

    • ROI区域
    • 灰度图转换
    • 图像增益设计
    • 图像尺寸调整
    • 图像混合,设定透明度
    • 图像合并,并列显示

基本图像操作

方法 描述 示例
rect 设定矩形框 Rect rect(100, 100, 200, 200); Mat roi = src(rect);//提取src数据中矩形框标定的数据,此时roi指向了src图片对应的矩形数据,是指针!
cvtColor 图片类型转换 cvtColor(src, gray, COLOR_BGR2GRAY); //BGR转灰度图
threshold 二进制阈值化 threshold(gray, bin, 100, 255, THRESH_BINARY); //大于100全部设为255:白色; 小于100的设为0:黑色; threshold(gray,ibin, 100, 255, THRESH_BINARY_INV);//反二进制阈值化
resize 图片尺寸调整 resize(src, des1024, Size(1024, 1024), 0, 0, INTER_LINEAR);
pyrDown 高斯金字塔,下采样 pyrDown(src, gsrc);高斯金字塔(Gaussian pyramid):用来向下采样–下采样:图像成倍缩小
pyrUp 拉普拉斯金字塔,上采样 pyrUp(src, lsrc);//拉普拉斯金字塔(Laplacian pyramid):用来从金字塔低层图像重建上层未采样图像 — 上采样:图像成倍增大
addWeighted 图像混合 addWeighted(img1, a, img2, 1 - a, 80, dst); // addWeighted:加权; //a:img1的权重,取值范围[0,1]; dst:生成图像
rotate 图像旋转 cv::rotate(img, rot, ROTATE_90_CLOCKWISE); // cv::rotate cv命名空间下的rotate函数,因此函数太容易被其他库中的函数名冲突。
flip 图像镜像 cv::flip(img, fl, 1); // type:0(围绕x轴镜像),1(围绕y轴镜像),-1(围绕x和y轴做镜像)

ROI区域

#include 
#include 
#include 
#include 
using namespace cv;
using namespace std;
int main(int argc, char *argv[])
{
	Mat src = imread("1.png");
	Rect rect(100, 100, 200, 200);
	Mat roi = src(rect);  //浅拷贝,只赋值了矩阵头

	namedWindow("src");
	namedWindow("roi");
	moveWindow("roi", 512, 0);  //图像显示窗口的位置移动
	imshow("src", src);
	imshow("roi", roi);
	waitKey(0);
	return 0;
}

//图像ROI提取 、 放回
Mat binNowX = matFenge(rectBinX).clone();  //获取对应的数据
binNowX.copyTo(BinaryTemplete(rectBinX));  //局部像素复制。原理是将(Mat *)binNowX拷贝到BinaryTemplete的rectBinX区域。

灰度图转换

void RGBToGray(Mat &src, Mat &des)
{
	// GRay = (R*30 + G*59 + B*11 +50)/100
	des.create(src.rows,src.cols,CV_8UC1);
	for (int r = 0; r < src.rows; r++)
	{
		for (int c = 0; c < src.cols; c++)
		{
			Vec3b &m = src.at<Vec3b>(r, c);    //3位的向量,  Vec3b: BGR
			int gray = (m[2] * 30 + m[1] * 59 + m[0] * 11 + 50) / 100;   //Mat:BGR
			des.at<uchar>(r, c) = gray;
		}
	}
}
int main(int argc, char *argv[])
{
	Mat src = imread("1.png");
	src.create(3000, 4000, CV_8UC3);   //重新创建src内容,  imread内容被删除了;为了体现多线程转换的优势,采用了大的图像。
	Mat gray;
	PrintMs("");
	cvtColor(src, gray, COLOR_BGR2GRAY);  //采用了多线程,但是第一次由于启动线程等,耗时较久。424ms
	PrintMs("cvtColor1");

	cvtColor(src, gray, COLOR_BGR2GRAY);  //第二次转换则是多线程的优势,转换非常快。17ms
	PrintMs("cvtColor2");
	Mat mygray;
	RGBToGray(src, mygray);    //自己转换,单个函数,耗时77ms
	PrintMs("RGBToGray");

	namedWindow("src");
	namedWindow("gray");
	namedWindow("mygray");

	imshow("src", src);
	imshow("gray", gray);
	imshow("mygray", mygray);

	waitKey(0);
	return 0;
}

图像增益设计

//
///@para a float 对比度 1.0~3.0
///@para b int 亮度 0~100
void ChangeGain(Mat &src, Mat &des, float a, int b)
{
	//g(r,c) = a*f(r,c) + b
	des.create(src.rows, src.cols, src.type());
	for (int r = 0; r < src.rows; r++)
	{
		for (int c = 0; c < src.cols; c++)
		{
			for (int i = 0; i < 3; i++)
			{
				des.at<Vec3b>(r, c)[i] = saturate_cast<uchar>(a * src.at<Vec3b>(r, c)[i] + b);   //saturate_cast:防止溢出;超过uchar的值255就设定为255
			}
		}
	}
}
int main(int argc, char *argv[])
{
	//调整对比度和亮度   ;   gain:增益 
	Mat src = imread("2.jpg");
	Mat des;
	PrintMs("");
	ChangeGain(src,des, 2.0,50);  //对比度:2.0;  亮度:+50;
	PrintMs("ChangeGain");
	Mat des2;
	src.convertTo(des2, -1, 2.0, 50);  //opencv提供的函数,-1:负数代表与原图的类型一致; 性能比自己写的 函数性能高。
	PrintMs("convertTo");

	namedWindow("src");
	namedWindow("des");
	namedWindow("des2");
	imshow("src", src);
	imshow("des", des);
	imshow("des2", des2);
	waitKey(0);
	return 0;
}

图像尺寸调整

void xresize(Mat &src, Mat &des, Size size)  // Size:是cv命名空间的Size,很容易冲突的类型。
{
	des.create(size, src.type());
	//映射的原图坐标
	int sx, sy = 0;
	float fx = (float)src.cols / des.cols;   // 原图列数(宽度)/目标图列数     
	float fy = (float)src.rows / des.rows;  // 原图的行数(高度)/目标图的行数
	for (int x = 0; x < des.cols; x++)
	{
		sx = fx * x + 0.5;   // int类型,四舍五入
		for (int y = 0; y <des.rows; y++)
		{
			sy = fy * y + 0.5;
			des.at<Vec3b>(y, x) = src.at<Vec3b>(sy, sx);  // 目标坐标的内容值等于原图相应坐标的内容值
		}
	}
}
int main(int argc, char *argv[])
{
	//图像尺寸调整算法,手动实现近邻算法;放大/缩小
	Mat src = imread("1.png"); //512*512 256 1024
	Mat img256,img1024,des256,des1024;
	resize(src, des256, Size(256, 256), 0, 0, INTER_NEAREST);

	PrintMs();
	//xresize(src, img256, Size(256, 256));
	//PrintMs("img256");
	xresize(src, img1024, Size(1024, 1024));
	//resize(src, img1024, Size(4024, 4024), 0, 0, INTER_NEAREST);
	PrintMs("img1024");
	//resize(src, des256, Size(1024, 1024), 0, 0, INTER_NEAREST);  // 近邻算法:INTER_NEAREST   , 简单的临近值拷贝:放大时边角处容易出现马赛克。原来一个像素点复制成了一个大的范围像素;缩小的话会有内容损失。
	resize(src, des1024, Size(1024, 1024), 0, 0, INTER_LINEAR);   //双线性内插值算法(缺省使用的算法),不是简单的拷贝,而是做了临近的运算;输出像素是输入邻域像素的加权和。
	//源图像位置在它附近的2*2区域4个临近像素的值通过加权平均计算得出的。低通滤波性质,使高频分量受损,图像轮廓可能会模糊一点。

	PrintMs("des1024"); 

	namedWindow("src");
	//namedWindow("img256");
	namedWindow("des1024");
	namedWindow("img1024");
	imshow("src", src);
	imshow("img1024", img1024);
	imshow("des1024", des1024);
	moveWindow("des1024", 512, 0);  //图像显示窗口的位置移动

	//imshow("img1024", img1024);
	waitKey(0);
	return 0;
}

图像混合,设定透明度

int main(int argc, char *argv[])
{
	Mat img1 = imread("1.png");
	Mat img2 = imread("2.png");
	resize(img2, img2, img1.size());  //!!!图像大小必须一样;
	Mat dst;
	float a = 0.8;
	addWeighted(img1, a, img2, 1 - a, 80, dst);   // addWeighted:加权; //a:img1的权重,取值范围[0,1]; dst:生成图像

	namedWindow("blending");
	imshow("blending", dst);
	waitKey(0);
	return 0;
}

图像合并,并列显示

/************************************************************************
注意:
	Mat r1 = des(Rect(0, 0, width1, height));  //1号图,!!!: des(Rect())这个并不会新创建Mat r1数据,而是将r1这个指针对象指向des这个图,对des进行直接改变。
	**********************************************************************/
#include 
int main(int argc, char *argv[])
{
	Mat img1 = imread("1.png");
	Mat img2 = imread("2.png");
	int height = img1.rows;  //设定两幅图像高度统一, 宽度不统一
	int width1 = img1.cols;
	int width2 = img2.cols;
	// 将高度较高的图像等比缩放与低图像的高度一致
	if (img1.rows > img2.rows)
	{
		height = img2.rows;
		width1 = img1.cols * ((float)img2.rows / (float)img1.rows);  //等比缩放,高度一致,宽度等比例改变。
		resize(img1, img1, Size(width1, height));
	}
	else if(img1.rows < img2.rows)
	{
		width2 = img2.cols * ((float)img1.rows / (float)img2.rows);
		resize(img2, img2, Size(width2, height));
	}
	//创建目标Mat
	Mat des;
	des.create(height, width1 + width2, img1.type());  //创建, 谨记!!!该复用函数,此时参数第一个是高,第二个是宽
	Mat r1 = des(Rect(0, 0, width1, height));  //1号图,!!!: des(Rect())这个并不会新创建Mat r1数据,而是将r1这个指针对象指向des这个图,对des进行直接改变。
	img1.copyTo(r1);  // 将img1拷贝到r1区域,r1区域指针指向des,故而最终拷贝到了des定义的数据变量中。
	Mat r2 = des(Rect(width1, 0, width2, height));
	img2.copyTo(r2);

	namedWindow("des");
	imshow("des", des);
	waitKey(0);
	destroyAllWindows();
	return 0;
}

你可能感兴趣的:(QT+Opencv+VS,opencv,图像处理,计算机视觉)