OpenCV入门学习(3)

Opencv学习day03

出入每天学习点OpenCV,做做计算机视觉项目


前言

为了项目与论文需要,现在入门 OpenCV4学习,并且学习点深度学习的东西,希望有助于自身论文的研究,只是为了毕业。。。


一、内容

1. 颜色空间的缩减

有时有些关键像素就能表示出整幅图,为了减少计算量,可以对颜色空间进行缩减。
对于unchar类型只有0-255个值,进行颜色空间的缩减时可以//0-9用0替代,10-19-用10替代,20-29用20替代…以此类推。
涉及到知识点:

图像每个像素的访问方式:

1、利用指针访问像素值
2、利用at()函数访问像素
3、利用迭代器iterator访问像素

获取系统时间方式:

getTickCount();获取系统的振荡次数
getTickFrequency() 系统振荡频率
时间 = getTickCount()/getTickFrequency()

代码:

//颜色空间缩减
 void OpenCV_quick_day01Demo::colorSpaceReduction_demo(Mat &image) {
	 //0-9用0替代,10-19-用10替代,20-29用20替代
	 //由于uchar只有0-255个像素,先建立一张表,存储可能的值
	 uchar table[256];
	 int dividewith = 10;
	 int width = image.cols *image.channels();
	 int heigth = image.rows;
	 double startTime = static_cast<double>(getTickCount())/ getTickFrequency();

	 for (int i = 0; i < 256; i++)
	 {
		 table[i] = (i / dividewith)*dividewith;
	 }
	 //访问图片每一个像数值
	 //利用指针访问像素值
	 for (int i = 0; i < heigth; i++) {
		 uchar * current_row = image.ptr<uchar>(i);
		 for (int j = 0; j < width; j++)
		 {
			 current_row[j] = table[current_row[j]];
		 }
	 }
	 //利用at()函数访问像素
	 /*for (int i = 0; i < heigth; i++)
	 {
		 for (int j = 0; j < image.cols; j++)
		 {
			 image.at<Vec3b>(i, j)[0] = table[image.at<Vec3b>(i, j)[0]];
			 image.at<Vec3b>(i, j)[1] = table[image.at<Vec3b>(i, j)[1]];
			 image.at<Vec3b>(i, j)[2] = table[image.at<Vec3b>(i, j)[2]];
		 }
	 }*/
	 //利用迭代器访问像素点
	 /*
	 Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
	 Mat_<Vec3b>::iterator itend = image.end<Vec3b>();

	 for (; it != itend; it++) {
		 (*it)[0] = table[(*it)[0]];
		 (*it)[1] = table[(*it)[1]];
		 (*it)[2] = table[(*it)[2]];
	 }
	 */
	 double endTime = static_cast<double> (getTickCount())/ getTickFrequency();
	 double runTime = endTime - startTime;
	 imshow("colorSpaceReduction", image);

	 cout << "程序运行时间:" << runTime << endl;
 }


2. 获取ROI区域

 void OpenCV_quick_day01Demo::ROI_demo() {
	 Mat srcImage = imread("E:/OpenCVcode/imageRead/aloeR.jpg");
	 Mat logoImage = imread("E:/OpenCVcode/imageRead/apple.jpg");
	 Mat imageROI;

	 //在srcImage上,ROI 区域左顶点为(200,200),长logoImage.cols,宽logoImage.rows
	 imageROI = srcImage(Rect(200, 200, logoImage.cols, logoImage.rows));

	 Mat mask = imread("E:/OpenCVcode/imageRead/apple.jpg", 0);
	 logoImage.copyTo(imageROI, mask);
	 namedWindow("ROI", WINDOW_FREERATIO);
	 imshow("ROI", srcImage);
 }

3. ROI 与线性叠加

addWeighted:

void addWeighted(InputArray src1, double alpha, InputArray src2,
                              double beta, double gamma, OutputArray dst, int dtype = -1);

第一个参数:要叠加的第一个图像Mat
第二个参数:标识第一个参数叠加的权重
第三个参数:表示第二个叠加的图像,他需要和第一个数组拥有同样的尺寸和通道数
第四个参数:表示第二个叠加图像的权重
第五个参数:输出参数,需要和前两个图像拥有同样的通道数和尺寸
第六个参数:一个加到权重总和上的标量值(填0就好)
第七个参数:输出阵列的深度有默认值-1, 当两张叠加图片深度相同时,参数为-1
对应表达式为:dst = src1[i] * alpha + src2[i] * beta + gamma;

 void OpenCV_quick_day01Demo::ROI_LinearBlending() {
	 Mat srcImage = imread("E:/OpenCVcode/imageRead/aloeR.jpg");
	 Mat logoImage = imread("E:/OpenCVcode/imageRead/apple.jpg");
	 Mat imageROI;
	 imageROI = srcImage(Rect(200, 200, logoImage.cols, logoImage.rows));

	 addWeighted(imageROI, 0.5, logoImage, 0.3, 0.0, imageROI);
	 namedWindow("ROI", WINDOW_FREERATIO);
	 imshow("ROI_linearBlending",srcImage);
 }
 

4. 离散傅里叶变换

getOptimalDFTSize:

int getOptimalDFTSize(int vecesize);返回DFT最优尺寸大小,vecesize向量尺寸,即图片的rows,cols

copyMakeBorder:

void copyMakeBorder(InputArray src, OutputArray dst,int top, int bottom, 
				int left, int right,int borderType,
			const Scalar& value = Scalar() )

————扩充图像边沿尺寸
int top, int bottom,int left, int right,在原图像扩充多少像素
int borderType,边界类型常见取值,BORDER_CONSTANT
const Scalar& value = Scalar() :要填充的值。Scalar类型

magnitude:

void magnitude(InputArray x, InputArray y, OutputArray magnitude)计算二维矢量的幅值

InputArray x, 实部,, InputArray y,虚部 OutputArray magnitude 输出的幅值

dft:

void dft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0);

对一维或二维浮点数数组进行正向或反向离散傅里叶变换
第一个参数:InputArray类型的src。输入矩阵,可以为实数或者虚数
第二个参数:OutputArray类型的dst。函数调用后的运算结果存在这里,其尺寸和类型取决于标识符,也就是第三个参数flags
第三个参数:int类型的flags。转换的标识符,有默认值0,取值可以为为下表:
在这里插入图片描述
第四个参数:int类型的nonzeroRows,默认值为0.当此参数设为非零时,函数会假设只有输入矩阵的第一个非零行包含非零元素,或只有输出矩阵的一个非零行包含非零元素。

normalize:

void normalize(InputArry src,InputOutputArray dst,double alpha=1,double beta=0,int norm_type=NORM_L2,int dtype=-1,InputArray mark=noArry())

归一化数据。
src 输入数组;
dst 输出数组,数组的大小和原数组一致;
alpha 1,用来规范值,2.规范范围,并且是下限;
beta 只用来规范范围并且是上限;//为0时则为值归一化,否则为范围归一化
norm_type 归一化选择的数学公式类型;
NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化,一般较常用。
NORM_INF:此类型的定义没有查到,根据OpenCV 1的对应项,可能是归一化数组的C-范数(绝对值的最大值)
NORM_L1 : 归一化数组的L1-范数(绝对值的和)
NORM_L2: 归一化数组的(欧几里德)L2-范数

dtype 当为负,输出在大小深度通道数都等于输入,当为正,输出只在深度与输如不同,不同的地方游dtype决定;
mark 掩码。选择感兴趣区域,选定后只能对该区域进行操作。

 void OpenCV_quick_day01Demo::dft_demo(Mat &image)//傅里叶变换
 {
	 //原程序
	 //1、先将原图转化为灰度图,扩大原图像到合适尺寸,一般位2,3,5的整数倍最快。
	 //利用getOptimalDFTSize获得合适尺寸,再用copyMakeBorder扩展边缘像素
	 Mat srcImage;
	 cvtColor(image, srcImage, COLOR_BGR2GRAY);

	 int m = getOptimalDFTSize(srcImage.rows);
	 int n = getOptimalDFTSize(srcImage.cols);
	 cout << m << endl;

	  Mat newImage;
	 copyMakeBorder(srcImage, newImage, 0, m - srcImage.rows, 0, n - srcImage.cols, BORDER_CONSTANT, Scalar::all(0));
	 newImage.convertTo(newImage, CV_32F);
	 cout << newImage.size();

	 //2.为傅里叶变换的结果(实部和虚部),分配存储空间
	  Mat planes[] = { newImage, Mat::zeros(newImage.size(),CV_32F) };
	 Mat complex;
	 merge(planes, 2, complex);

	 //3.进行离散傅里叶变换
	 dft(complex, complex);
	 //4.将变换后的复数转换为幅值
	 Mat channels[2];
	 split(complex, channels);//先分离出实部和虚部
	 Mat magnitudeValue;
	 magnitude(channels[0], channels[1], magnitudeValue);//转换成幅值


	 //5.所得的幅值太大, 进行尺度缩放
	 magnitudeValue += Scalar::all(1);
	 log(magnitudeValue, magnitudeValue);

	 //6.剪切和重分布幅度图象限,一四象限对调,二三象限对调。
	 //若有奇数行或奇数列,进行频谱裁剪
	 magnitudeValue = magnitudeValue(Rect(0, 0, magnitudeValue.cols & -2, magnitudeValue.rows & -2));
	 int x = magnitudeValue.cols / 2;
	 int y = magnitudeValue.rows / 2;

	 //剪切幅度图象限
	 Mat q0 = magnitudeValue(Rect(0, 0, x, y));
	 Mat q1 = magnitudeValue(Rect(x , 0, x, y));
	 Mat q2 = magnitudeValue(Rect(0, y, x, y));
	 Mat q3 = magnitudeValue(Rect(x, y, x, y));

	 //重分布幅度图象限,一四交换,二三交换
	 Mat temp;
	 q0.copyTo(temp);
	 q3.copyTo(q0);
	 temp.copyTo(q3);

	 q1.copyTo(temp);
	 q2.copyTo(q1);
	 temp.copyTo(q2);
	 
	 //归一化处理
	 normalize(magnitudeValue, magnitudeValue, 0, 1, NORM_MINMAX);

	 imshow("频谱幅值", magnitudeValue);	 
 }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值