OpenCV中包含core组件,这个大组件包含一些图像的基本操作,简述下几个模块:
1:操作图像像素:有三种方式
a. 指针访问:C操作符[],一般就是*data[],速度最快
b. 迭代器iterator,
Mat_::iterator it = outputImage.begin();//初始位置迭代器
Mat_::iterator itend = outputImage.end();//终止位置的迭代器
for(;it != itend;++it)
{
(*it)[0] = ( *it )[0]/div *div + div/2;
(*it)[1] = ( *it )[1]/div *div + div/2;
(*it)[2] = ( *it )[2]/div *div + div/2;
}
c. 动态地址计算,outputImage.at(i,j)[0],就是用at存取图像元素。
设置感兴趣区域:
两种方法:
一使用表示矩形区域的Rect,指定矩形的左上角坐标和矩形的长宽。
imgROI = image(Rect(500,250,logo.cols,logo.rows));
二是指定感兴趣的行或列的范围(Range)。 imgROI=image(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));
线性混合操作:是典型的二元(两个输入)的像素操作:
g(x)=(1-a)f1(x)+af2(x),比如透明度不同的两幅图
这里实现的话要使用数组加权和addWeighted()函数
addWeighted(in1,a,in2,b,g,out,-1);
颜色通道的问题
通道分离:split(src,outArrayOfArrays); //第二个参数是一个容器
通道合并:merge(InputArrayOfArray mv,outputArray dst); //孤立的单通道数组合并成一个多通道的数组。
图像对比度、亮度值调整
这个就是根据像素值进行操作的,g(i,j)=a*f(i,j)+b, a一般大于0,是增益,用来控制图像的对比度。b成为偏置,控制亮度。
离散傅里叶变换
这是指傅里叶变换在时域和频域都呈现离散的形式,将时域信号的采样变换为在离散时间傅里叶变换频域的采样。可以将图像分解为正玄和余弦两部分,从空间域转换到频域。就变换成幅度图像加相位图像。在频域,高频部分代表图像的细节、纹理信息,低频代表图像的轮廓信息。这样傅里叶变换就可以做图像增强,图像去噪、图像分割之边缘检测、图像特征提取、图像压缩等。
dft(in,out,flag,int nonzeroRows=0);
还有个得到DFT最优尺寸大小的:getOptimalDFTSize(int vecsize)函数。
扩充图像边界:
void copyMakeBoarder(src,dst,top,bottom,left,right,borderType,Scalar&value=Scalar())
中间四个参数是在四个方向上各扩充两个像素宽度的边界。
计算二维矢量的幅值:void magnitude(in,in,out);第一个是实部,二是虚部,三输出幅值。
计算自然对数:log(src,dst);
矩阵归一化:normalize的作用是进行矩阵归一化
下面有个示例对图像求傅里叶变换:
//---------------------------------【头文件、命名空间包含部分】-----------------------------
// 描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
using namespace cv;
//-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
printf("\n\n\t\t\t此为本书OpenCV3版的第28个配套示例程序\n");
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION );
printf("\n\n ----------------------------------------------------------------------------\n");
}
//--------------------------------------【main( )函数】-----------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-------------------------------------------------------------------------------------------------
int main( )
{
//【1】以灰度模式读取原始图像并显示
Mat srcImage = imread("1.jpg", 0);
if(!srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); return false; }
imshow("原始图像" , srcImage);
ShowHelpText();
//【2】将输入图像延扩到最佳的尺寸,边界用0补充
int m = getOptimalDFTSize( srcImage.rows );
int n = getOptimalDFTSize( srcImage.cols );
//将添加的像素初始化为0.
Mat padded;
copyMakeBorder(srcImage, padded, 0, m - srcImage.rows, 0, n - srcImage.cols, BORDER_CONSTANT, Scalar::all(0));
//【3】为傅立叶变换的结果(实部和虚部)分配存储空间。
//将planes数组组合合并成一个多通道的数组complexI
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat complexI;
merge(planes, 2, complexI);
//【4】进行就地离散傅里叶变换
dft(complexI, complexI);
//【5】将复数转换为幅值,即=> log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
split(complexI, planes); // 将多通道数组complexI分离成几个单通道数组,planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
Mat magnitudeImage = planes[0];
//【6】进行对数尺度(logarithmic scale)缩放
magnitudeImage += Scalar::all(1);
log(magnitudeImage, magnitudeImage);//求自然对数
//【7】剪切和重分布幅度图象限
//若有奇数行或奇数列,进行频谱裁剪
magnitudeImage = magnitudeImage(Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));
//重新排列傅立叶图像中的象限,使得原点位于图像中心
int cx = magnitudeImage.cols/2;
int cy = magnitudeImage.rows/2;
Mat q0(magnitudeImage, Rect(0, 0, cx, cy)); // ROI区域的左上
Mat q1(magnitudeImage, Rect(cx, 0, cx, cy)); // ROI区域的右上
Mat q2(magnitudeImage, Rect(0, cy, cx, cy)); // ROI区域的左下
Mat q3(magnitudeImage, Rect(cx, cy, cx, cy)); // ROI区域的右下
//交换象限(左上与右下进行交换)
Mat tmp;
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
//交换象限(右上与左下进行交换)
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
//【8】归一化,用0到1之间的浮点值将矩阵变换为可视的图像格式
//此句代码的OpenCV2版为:
//normalize(magnitudeImage, magnitudeImage, 0, 1, CV_MINMAX);
//此句代码的OpenCV3版为:
normalize(magnitudeImage, magnitudeImage, 0, 1, NORM_MINMAX);
//【9】显示效果图
imshow("频谱幅值", magnitudeImage);
waitKey();
return 0;
}