【opencv2】生成图像的梯度图

63 篇文章 1 订阅

转载来自:http://blog.csdn.net/autocyz/article/details/43193123

求解梯度图,首先要注意数据的转换。因为本身读取的图像是8位的,其灰度值范围为0~255,而在求梯度的过程中,会出现梯度值大于255或者小于0的情况,因此在梯度图所存储的数据应该是以有符号整型的形式,即CV_32S。

另外,我采用的梯度求解方法为,当前像素的后一个像素减前一个像素的差值,作为当前像素的当前方向的梯度值。因为梯度本质上是求微分,因此对与图像,其存在两个方向上的梯度,即水平和垂直方向。这也是程序中求了两次灰度的原因。

在求了两个方向的梯度之后,再如何求出当前像素的梯度值,其方法也是很多的。我采用的是将水平和垂直梯度的绝对值相加,也可以采用平方和再开根号的方法,或者直接取二者最大值都行。

另外,解释一下,最后的那个类型转换函数,其作用是将当前数据类型的图像转换为unsigned char型,另外,在OpenCV中,其重载了很多算术运算符,比如这个函数里面的Ix+Iy就是代表对应位相加。

#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\core\core.hpp>
#include <iostream>
using namespace cv;
using namespace std;

typedef unsigned char byte;
void gradientGray(Mat &src, Mat &mag);
int main(){

	Mat src = imread("D:\\ymrf\\enhance\\paper\\test_img\\1.jpg");//以灰度形式读取图片
	Mat dst;
	cvtColor(src,dst,CV_RGB2GRAY);
	gradientGray(dst, dst);
//	imwrite("2.jpg", dst); //保存文件,梯度图
	namedWindow("src", 0);
	namedWindow("dst",0);
	imshow("src", src);
	imshow("dst", dst);
	waitKey(0);

}

void gradientGray(Mat &src, Mat &mag)
{
	const int H = src.rows, W = src.cols;
	Mat Ix(H, W, CV_32S), Iy(H, W, CV_32S);
	//因为计算出的梯度值可能有正有负,且值也可能会很大,故数据类型为整形

	// 求水平方向梯度,处理左右边缘像素
	for (int y = 0; y < H; y++){
		Ix.at<int>(y, 0) = abs(src.at<byte>(y, 1) - src.at<byte>(y, 0)) * 2;
		for (int x = 1; x < W - 1; x++)
			Ix.at<int>(y, x) = abs(src.at<byte>(y, x + 1) - src.at<byte>(y, x - 1));
		Ix.at<int>(y, W - 1) = abs(src.at<byte>(y, W - 1) - src.at<byte>(y, W - 2)) * 2;
	}
	// 求垂直方向梯度,处理左右边缘像素
	for (int x = 0; x < W; x++)	{
		Iy.at<int>(0, x) = abs(src.at<byte>(1, x) - src.at<byte>(0, x)) * 2;
		for (int y = 1; y < H - 1; y++)
			Iy.at<int>(y, x) = abs(src.at<byte>(y + 1, x) - src.at<byte>(y - 1, x));
		Iy.at<int>(H - 1, x) = abs(src.at<byte>(H - 1, x) - src.at<byte>(H - 2, x)) * 2;
	}
	/*for (int j = 0; j < H; j++)
	for (int k = 0; k < W; k++)
	{
	mag.at<byte>(j, k) = min(Ix.at<int>(j,k) + Iy.at<int>(j, k), 255);
	}*/
	convertScaleAbs(min(Ix + Iy, 255), mag); //这句话和上面的for循环是同样的功能
}

感冒 明天国庆 哈哈 偷笑


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值