不得不说的opencv 那些事

初次接触图像类的代码编辑,有很多新奇的东西值得去探讨研磨,在opencv 代码库编辑环境下,初次认知了图像代码处理的最基本的知识。

1.矩阵和图像的关系

在opencv 中,Mat 一个矩阵即为生成了一个图像,可对这个矩阵进行Imshow(),imread()等图像处理。以单通道的灰度图为例,矩阵中每一个数值对应图像中一个像素点的灰度值,矩阵中这些数值的有序排布就构成了一个图像。

Mat m1 = Mat::eye(500, 500, CV_64FC1);
//cout << m1 << endl;
imshow("www", m1);
waitKey(0);

以上代过编辑一个单位矩阵并输出,可以看到输出的图形恰为对角线为亮线的图形。


同样,读入一个图片,也可以输出这个图片任意一点的像素值。

Mat img = imread("pic.jpg", 0);				//读入一个单通道的灰度图
cout << img.type() << endl;					//输出图片像素的数据类型
cout << (int)img.at<uchar>(1, 1) << endl;		//输出这个图片在(1, 1)点的像素值
imshow("www",img);
waitKey(0);

2.矩阵的基本运算

opencv 中定义了基本的矩阵运算函数和运算符重载,以便于用户进行图像的操作.

int row = 5;
//创建一个单位矩阵
Mat img = Mat::eye(5, 5, CV_64FC1);
cout << img << endl << endl;

//分别创建元素都为0和都为1的矩阵
Mat imagezeros = Mat::zeros(row, 5, CV_64FC1);
Mat imageones = Mat::ones(5, 5, CV_64FC1);
	
//可以直接进行像素元素的相乘
Mat img2 = img*imageones + 1;
cout << img2 << endl << endl;

//把一个图像元素内容拷贝到另一图像中
img.copyTo(img2);
cout << img2 << endl << endl;
//求一个图像矩阵的逆矩阵
cout << img.inv() << endl;

3.对图像矩阵的求导

以单通道的图片为例,对图像的像素点进行x方向求导,可以得到图像在这个点x方向的明亮强度变化的大小。同时图像梯度: G(x,y) = dx(i,j) + dy(i,j),通过导数可以得到这个点的明暗梯度大小。求导公式: dx(i,j) = I(i+1,j) - I(i,j), dy(i,j) = I(i,j+1) - I(i,j)

Mat img = imread("pic.jpg", 0);
 cout << "row  " << img.rows << "  col  " << img.cols << endl;

 Mat dimg1 = Mat(img.rows, img.cols-2, CV_8UC1);
 Mat dimg2 = Mat(img.rows, img.cols-2, CV_8UC1);

 /*
 *第一种方法,直接求导并存储
 */
 for( int i = 0; i < img.rows; i++)
 {
  for(int j = 1; j < img.cols - 1; j++)
  {
   dimg1.at<uchar>(i , j-1) = img.at<uchar>(i, j-1) - img.at<uchar>(i , j + 1);
  }
 }

 /*
 *第二种方法,定义卷积模板实现
 */
 Mat model = Mat(1, 3, CV_64FC1);
 model.at<double>(0, 0) = 1;
 model.at<double>(0, 1) = 0;
 model.at<double>(0, 2) = -1;

 for (int i = 0; i<img.rows; i++)
 {
  for (int j = 1; j<img.cols - 1; j++)
  {
   int half = model.cols / 2;
   double sum = 0;
   for (int m = 0; m<model.rows; m++)
   {
    for (int n = -half; n<model.cols - half; n++)
    {
     sum += (double)(img.at<uchar>(i + m, j + n))*model.at<double>(m, n + half);//(double)为强制转化成double类型
    }
   }
    dimg2.at<uchar>(i, j - 1) = (uchar)sum;
  }
 }

 imshow("unchanged", img);
 imshow("changedOne", dimg1);
 imshow("changedTwo", dimg2);
 waitKey(0);

把三幅图片放在一起来看

4.滤镜的出现和原理

滤镜就是一个矩阵,使用不同的滤镜不同的矩阵作为卷积核,对原图像进行卷积操作可以得到很多不同风格的效果,功能十分强大。

/*
*定义一个5*5的高斯模板矩阵, 并做归一化处理。
*/
Mat gauss(5, 5, CV_64FC1);
double sigma = 5;
for( int i = -2; i < 3; i++)
{
	for(int j = -2; j < 3; j++)
	{
		gauss.at<double>(i + 2, j + 2) = exp(-(i*i + j*j)/(2*sigma*sigma));
	}
}
double gssum = sum(gauss).val[0];
for( int i = -2; i < 3; i++)
{
	for(int j = -2; j < 3; j++)
	{
		gauss.at<double>(i + 2, j + 2)/=gssum;
	}
}
//cout << gauss << endl;
	
/*
*使用高斯模板分别在 x 和 y 两个方向上进行卷积操作
*/
Mat img = imread("pic.jpg", 0);
Mat dimg = Mat(img.rows - 4, img.cols - 4, CV_8UC1);
for( int i = 2; i < img.rows-2; i++)
{
	for( int j = 2; j < img.cols-2; j++)
	{
		double sum = 0;
		for( int m = 0; m < gauss.rows; m++)
		{
			for( int n= 0; n < gauss.cols; n++)
			{
				sum += (double)img.at<uchar>(i + m - 2, j + n -2)*gauss.at<double>(m, n);
			}
		}
	dimg.at<uchar>(i-2, j-2) = (uchar)sum;
	}
}
imshow("unchanged", img);
imshow("changed", dimg);
waitKey(0);

代码的效果清晰可见


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值