学习opencv的笔记,其中很多是复制粘贴其他大佬的,整理自用,侵删!
详细的步骤其他人已经写的很详细了,就有一个ippicv_2020_lnx_intel64_20191018_general 文件下载不下来,从网上下载后保存在本地,再把路径改为本地,后面试了好久,有一个md5的报错,先删除编译产生的文件再编译,不要直接继续编译!!!!!!!!!!别问我咋知道的
Mat 是一个基本图像容器,也是一个类,数据由两个部分组成: 矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩阵(根据所 选存储方法的不同矩阵可以是不同的维数)的指针。
Mat imread( const String& filename, int flags = IMREAD_COLOR );
功能:读取图片文件中的数据
参数:filename:图片路径
flags:指定读取图片的颜色类型,注意:opencv 版本不同,宏可能不一样
opencv3.2.0 中 IMREAD_GRAYSCALE 值为 0,表示显示灰度图 IMREAD_COLOR 值为 1,表示显示原图
返回值:Mat 类对象
我是用vscode+cmake编译的,add_executable(caiji 01读取.cpp)中caiji这里一定不要写成中文,搞了大半天才发现
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("./../img/girl.jpg",IMREAD_GRAYSCALE);
// namedWindow("输出窗口",WINDOW_FREERATIO); //当图像太大是可以用WINDOW_FREERATIO,创建窗口
imshow("input",src); //input是显示窗口的名称
waitKey(0); //
destroyAllWindows(); //清除所有显示的窗口
return 0;
}
//读取图像可选参数
//! Imread flags
enum ImreadModes {
IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image.
IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image.
IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format.
IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image.
IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
IMREAD_REDUCED_COLOR_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
IMREAD_REDUCED_COLOR_8 = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
IMREAD_IGNORE_ORIENTATION = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
};
void namedWindow(const string& winname, int flags=WINDOW_AUTOSIZE) 的功能就是新建一个显示窗口。可以指定窗口的类型。
第一个参数:const string& 型的name,指用作窗口的表示符的窗口名称。
第二个参数:int类型的flags,窗口的标识,主要有以下几种。
flags标识种类:
WINDOW_NORMAL,可以更改窗口的大小(没有限制)。OpenCV2中可以写为CV_WINDOW_NORMAL。
WINDOW_AUTOSIZE,窗口大小会自动调整以适应所显示的图像,并且不能修改窗口大小。OpenCV2中可以写为CV_WINDOW_AUTOSIZE。此参数是默认值。
WINDOW_OPEMGL,窗口会支持OpenGL。OpenCV2中可以写为CV_WINDOW_OpenGL。
如果有相同名称的窗口已经存在,则函数不做任何事情。
调用destroyWindow()或者destroyALLWindow()函数来关闭窗口,并取消之前分配的与窗口相关的所有内存空间。
void imshow(const String& winname, InputArray mat);
功能:显示照片
参数:
winname:显示照片窗口的名称 注意这个参数,如果名字和创建窗口的一样,则会绑定在上面
mat:imread 的返回值
int waitKey(int delay = 0)
功能:在一个给定的时间内(单位 ms)等待用户按键触发,如果用户没有按下键,则一直阻塞
参数:delay:用于设置在显示完一帧,图像后程序等待“delay”ms 再显示下一帧视频,如果 waitKey(0) 则只会显示第一帧视频
返回值:按键的 ASCII 码值
(就是填100了,就延时100毫秒再关闭,填0了,就一直不关闭,如果按下按键、会返回按键的ASCII码值)
void putText( Mat& img, const string& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=8 );
功能:在图像上添加文字
参数:
img:待添加文字的图像
text:字符串,不支持中文
org:待写入的首字符左下角坐标
fontFace:字体类型,FONT_HERSHEY_SIMPLEX ,FONT_HERSHEY_PLAIN ,FONT_HERSHEY_DUPLEX 等
fontScale:字体大小
color:字体颜色,颜色用 Scalar(BGR)表示 T
hickness:字体粗细 lineType:
线型,默认值是 8
保存图片并显示
#include
#include
using namespace std;
using namespace cv;
//这里用到main函数的参数了,argv[]是一个数组,第一个存的是本身文件,后面的是传进去的参数
int main(int argc, char const *argv[])
{
if(argc < 2){
cout<<"./opencv_t *.jpg"<<endl;
return -1;
}
//实例化对象保存图片的信息
//Mat image = imread(argv[1]);
Mat image = imread(argv[1],IMREAD_GRAYSCALE);//IMREAD_COLOR
//判断图片是否为空
if(image.empty()){
cout << "Do not load image..." << endl;
return -1;
}
putText(image,"hello caiji",Point(50,50),FONT_HERSHEY_SIMPLEX,1,Scalar(0,255,0),1);
//显示图片
imshow("This is a image", image);
waitKey(0);
return 0;
}
cvtColor(src,gray,COLOR_BGR2GRAY);
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat hsv,gray;
Mat src = imread("./../img/qiaoba.jpg");
namedWindow("输出窗口",WINDOW_FREERATIO);
if(src.empty())
{
printf("could not load image\n");
}
cvtColor(src,hsv,COLOR_BGR2HSV);
cvtColor(src,gray,COLOR_BGR2GRAY);
imshow("hsv",hsv);
imshow("gray",gray);
imwrite("./hsv.jpg",hsv);
imwrite("./gray.jpg",gray); //保存图片
waitKey(0);
destroyAllWindows();
return 0;
}
图像色彩空间转换 这个是bgr转hsv
相关链接
H、S、V三个通道,分别为色调、饱和度、亮度,其中H的取值范围是[ 0, 180 ],S和V的取值范围是[ 0 , 255 ]。因为HSV图像存在色调这一通道,而不同颜色的色调都是不同的,所以我们可以通过规定色调通道的不同取值范围从而来提取出不同的颜色
Mat详解
opencv中mat详细解析
深拷贝图像:
Mat m1 = image.clone();
image.copyTo(m1);
对于openCv中copyTo()的用法有以下两种:
image.copyTo(imageROI)。作用是把image的内容复制粘贴到imageROI上;
image.copyTo(imageROI,mask)。 作用是把mask和image重叠以后把mask中像素值为0(black)的点对应的image中的点变为透明,而保留其他点。
给通道赋值
//创建空白图像
Mat m1 = Mat::zeros(Size(4,4),CV_8UC3);
m1 = Scalar(127,127,127); //给三个通道全赋值为127
一切图像皆Mat
OpenCV学习之Mat::at()理解
图像遍历操作
#include
#include
using namespace cv;
using namespace std;
int main()
{
// Mat src = Mat::zeros(Size(8,8),CV_8UC3);
// src = Scalar(0,255,255);
Mat src = imread("./../img/girl.jpg",IMREAD_GRAYSCALE);
Mat src1;
src.copyTo(src1);
int w = src.cols; //宽
int h = src.rows; //高
int dims = src.channels(); //通道数
std::cout<<"宽: "<<w<<"高: "<<h<<"通道数: "<<dims<<endl;
for (int raw= 0; raw < h; raw++)
{
for(int col=0; col<w;col++)
{
if(dims==1) //单通道灰度图
{
int pv=src1.at<uchar>(raw,col); //(y,x)
src1.at<uchar>(raw,col) = 255-pv;
}
if(dims==3) //彩色图片
{
Vec3b bgr = src1.at<Vec3b>(raw,col); //一次性获取三个值
src1.at<Vec3b>(raw,col)[0] = 255-bgr[0];
src1.at<Vec3b>(raw,col)[1] = 255-bgr[1];
src1.at<Vec3b>(raw,col)[2] = 255-bgr[2];
}
}
}
imshow("像素读写演示",src1);
waitKey(0);
destroyAllWindows();
return 0;
}
图片取反操作
取反后还是廷吓人的哈哈哈
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("./../img/girl.jpg",IMREAD_GRAYSCALE);
namedWindow("输出窗口",WINDOW_FREERATIO);
if(src.empty())
{
printf("could not load image\n");
}
src = src + Scalar(50,50,50);
imshow("input",src);
waitKey(0);
destroyAllWindows();
return 0;
}
执行除法时有这个报错
原因是两个图像类型不匹配
需要改成这样
执行后图像暗了好多
进行乘法时很容易溢出,
有一个专门的乘法函数
multiply(x1,x2,y)
可以看到乘法后亮了许多,应该是大于255的赋值为255
int createTrackbar(const String& trackbarname, const String& winname,
int* value, int count,
TrackbarCallback onChange = 0,
void* userdata = 0);
参数1:滑动条轨迹名;
参数2:滑动条依附的窗口名; 注意这个参数,绑定窗口名称一定要和前面创建窗口名称一样,否则不显示VBar
参数3:滑块的位置,创建时,滑块初始位置就是这个变量当前的值;
参数4:轨迹的最大值;
参数5:回调函数;
参数6:默认0,用户传给回调函数的数据,如果第三个值为全局变量,忽略这个值.;如果使用第6个参数,则作为参数传给回调函数的usrdata。
#include
#include
using namespace cv;
using namespace std;
Mat dst,m,src;
int lightness = 50;
static void on_track(int , void *)
{
dst = Scalar(lightness,lightness,lightness);
add(dst,src,m);
//m = dst + src;
imshow("亮度调整",m);
}
int main()
{
src = imread("./../img/a9c5750678b49fb41656e6e3c1d9be91--799476803.jpg",IMREAD_COLOR);
namedWindow("亮度调整",WINDOW_NORMAL);
namedWindow("input",WINDOW_NORMAL);
if(src.empty())
{
printf("could not load image\n");
}
dst = Mat::zeros(src.size(),src.type());
m = Mat::zeros(src.size(),src.type());
int max_value = 100;
imshow("input",src);
on_track(50,0);
createTrackbar("Value Bar:","亮度调整",&lightness,max_value,on_track);
waitKey(0);
destroyAllWindows();
return 0;
}
这里还遇到点问题, == int lightness=50;== 这个变量放在main函数里面,调节滚动条图像不发生变化,放在外面就好了,不知道为啥…求路过的大佬赐教
简单重映射 :把一幅图像中某位置的像素放置到另一个图片指定位置的过程。
void remap(InputArray src, //输入图像
OutputArraydst, //输出图像
InputArray map1,//第一个映射
InputArray map2, //第二个映射
int interpolation, //插值
intborderMode=BORDER_CONSTANT,
const Scalar& borderValue=Scalar()
)
第三个参数,InputArray类型的map1,它有两种可能的表示对象:
表示点(x,y)的第一个映射。
表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值。
第四个参数,InputArray类型的map2,同样,它也有两种可能的表示对象,而且他是根据map1来确定表示那种对象。
若map1表示点(x,y)时。这个参数不代表任何值。
表示CV_16UC1 , CV_32FC1类型的Y值(第二个值)。
第五个参数,int类型的interpolation,插值方式,之前的resize( )函数中有讲到,需要注意,resize( )函数中提到的INTER_AREA插值方式在这里是不支持的,所以可选的插值方式如下:
INTER_NEAREST - 最近邻插值
INTER_LINEAR – 双线性插值(默认值)
INTER_CUBIC – 双三次样条插值(逾4×4像素邻域内的双三次插值)
INTER_LANCZOS4 -Lanczos插值(逾8×8像素邻域的Lanczos插值)
第六个参数,int类型的borderMode,边界模式,有默认值BORDER_CONSTANT,表示目标图像中“离群点(outliers)”的像素值不会被此函数修改。
第七个参数,const Scalar&类型的borderValue,当有常数边界时使用的值,其有默认值Scalar( ),即默认值为0。
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("./../img/girl.jpg",IMREAD_GRAYSCALE);
namedWindow("输出窗口",WINDOW_FREERATIO);
if(src.empty())
{
printf("could not load image\n");
}
int colormap[] = {
COLORMAP_AUTUMN ,
COLORMAP_BONE ,
COLORMAP_JET ,
COLORMAP_WINTER ,
COLORMAP_RAINBOW ,
COLORMAP_OCEAN ,
COLORMAP_SUMMER ,
COLORMAP_SPRING ,
COLORMAP_COOL ,
COLORMAP_HSV ,
COLORMAP_PINK ,
COLORMAP_HOT ,
COLORMAP_PARULA ,
};
Mat dst;
int index=0;
while (true)
{
int c = waitKey(1000);
if(c==27) break;
applyColorMap(src,dst,colormap[index%12]);
index++;
std::cout<<index%12<<endl;
imshow("输出窗口",dst);
}
destroyAllWindows();
return 0;
}
rectangle()
rectangle函数是用来绘制一个矩形框的,通常用在图片的标记上。
rectangle(img, Point(j,i), Point(j + img4.cols, i + img4.rows), Scalar(255, 255, 0), 2, 8);
img:被处理的图片
Point(j,i)代表矩形左上点的坐标
Point(j + cols, i + rows)代表矩形右下点的坐标【矩形的大小(cols,rows】
scalar:颜色
2代表线条宽度 -1就是全填充
8是线型,默认取8
Rect函数是画出图像中的矩形
Rect(x,y,width,height),x, y 为左上角坐标, width, height 则为长和宽。
Rect roi_rect = Rect(128, 128, roi.cols, roi.rows);
画圈用 circle()函数
画线用line()
画椭圆 ellipse()
#include
#include
using namespace cv;
using namespace std;
int main()
{
//namedWindow("输出窗口",WINDOW_FREERATIO);
Mat m1 = Mat::zeros(Size(256,256),CV_8UC3);
Mat m2 = Mat::zeros(Size(256,256),CV_8UC3);
rectangle(m1,Rect(100,100,80,80),Scalar(255,255,0),1,LINE_8,0);
rectangle(m2,Rect(150,150,80,80),Scalar(0,255,255),1,LINE_8,0);
imshow("m1",m1);
imshow("m2",m2);
waitKey(0);
destroyAllWindows();
return 0;
}
像素位操作
bitwise_and(m1,m2,dst);
bitwise_or(m1,m2,dst);
bitwise_not(bitwise_not(src,dst); 对原图取反操作
bitwise_xor(m1,m2,dst); 异或操作
先熟悉下这个
C++ / Opencv 学习笔记 (Vector用法 )
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("./../img/1612018340085.jpg",IMREAD_COLOR);
//namedWindow("输出窗口",WINDOW_FREERATIO);
if(src.empty())
{
printf("could not load image\n");
}
std::vector<Mat> a;
split(src,a);
std::cout<<src.channels()<<endl;
imshow("b色",a[0]);
imshow("g色",a[1]);
imshow("r蓝色",a[2]);
Mat dst;
a[1]=0;
a[2]=0;
merge(a,dst);
imshow("蓝色",dst);
waitKey(0);
destroyAllWindows();
return 0;
}
void split(const Mat& src,Mat *mvBegin)
第一个参数为要进行分离的图像矩阵,第二个参数可以是Mat数组的首地址,或者一个vector对象
void merge(const Mat* mv, size_t count, OutputArray dst);
第一个参数是图像矩阵向量容器,第二个参数是输出,这种方法无需说明需要合并的矩阵个数,vector对象自带说明
void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs)
mixChannels主要就是把输入的矩阵(或矩阵数组)的某些通道拆分复制给对应的输出矩阵(或矩阵数组)的某些通道中,其中的对应关系就由fromTo参数制定;
src:输入矩阵,可以为一个也可以为多个,但是矩阵必须有相同的大小和深度
nsrcs:输入矩阵的个数
dst:输出矩阵,可以为一个也可以为多个,但是所有的矩阵必须事先分配空间(如用create),大小和深度须与输入矩阵等
ndsts:输出矩阵的个数。
fromTo: 设置输入矩阵的通道对应输出矩阵的通道,规则如下:首先用数字标记输入矩阵的各个通道。输入矩阵个数可能多于一个并且每个矩阵的通道可能不一样, 第一个输入矩阵的通道标记范围为:0 ~ src[0].channels()-1,第二个输入矩阵的通道标记范围为:src[0].channels() ~ src[0].channels()+src[1].channels()-1,以此类推;其次输出矩阵也用同样的规则标记,第一个输出矩阵的通道标记范围为:0 ~ dst[0].channels()-1,第二个输入矩阵的通道标记范围为:dst[0].channels()~ dst[0].channels()+dst[1].channels()-1,以此类推;最后,数组fromTo的第一个元素即fromTo[0]应该填入输入矩阵的某个通道标记,而fromTo的第二个元素即fromTo[1]应该填入输出矩阵的某个通道标记,这样函数就会把输入矩阵的fromTo[0]通道里面的数据复制给输出矩阵的fromTo[1]通道。fromTo后面的元素也是这个道理,总之就是一个输入矩阵的通道标记后面必须跟着个输出矩阵的通道标记。
npairs:即参数fromTo中的有几组输入输出通道关系,其实就是参数fromTo的数组元素个数除以2.
void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)
检查数组元素是否在另外两个数组元素值之间。这里的数组通常也就是矩阵Mat或向量。请注意:该函数输出的dst是一幅二值化之后的图像。
主要是将在两个阈值内的像素值设置为白色(255),而不在阈值区间内的像素值设置为黑色(0),该功能类似于之间所讲的双阈值化操作。
参数1:输入要处理的图像,可以为单通道或多通道。
参数2:包含下边界的数组或标量。
参数3:包含上边界数组或标量。
参数4:输出图像,与输入图像src 尺寸相同且为CV_8U 类型。
可以利用该函数进行扣图,需要先把图像转为hsv的,再进行二值化,然后对产生的图取反、再把原图复制到该图上就可以了
在数组中找到全局最小和最大值。
void minMaxLoc(InputArray src, double* minVal, double* maxVal = 0, Point* minLoc = 0, Point* maxLoc = 0, InputArray mask = noArray());
src,输入的数组,若是图像,需为单通道图像。
minVal,返回最小值的指针。若无需返回,此值设为 NULL。
maxVal,返回最大值的指针。若无需返回,此值设为 NULL。
minLoc,返回最小值位置的指针(二维情况下)。若无需返回,此值设为 NULL。
maxVal,返回最大值位置的指针(二维情况下)。若无需返回,此值设为 NULL。
mask,可选的掩膜操作,非零掩码元素用于标记待统计元素,需要与输入图像集有相同尺寸。
void meanStdDev(InputArray src,OutputArray mean, OutputArray stddev, InputArray mask=noArray())
计算单通道矩阵所有元素均值和标准差的例子
src:输入矩阵,这个矩阵应该是1-4通道的,这可以将计算结果存在Scalar_ ‘s中
mean:输出参数,计算均值
stddev:输出参数,计算标准差
mask:可选参数
单通道计算相关数据
void pixel_statistic_domo(Mat &image){
double minv,maxv;
Point minLoc,maxLoc;
minMaxLoc(image,&minv,&maxv,&minLoc,&maxLoc,Mat());
std::cout<<"min value:"<<minv<<"max value:"<<maxv<<std::endl;
Mat mean,stddev;
meanStdDev(image,mean,stddev);
std::cout<<"means:"<<mean<<"stddev:"<<stddev<<std::endl;
}
用 mean.at(1,0) 相关用法在vector容器里面
再贴一遍 C++ / Opencv 学习笔记 (Vector用法 )
Point操作
Point是一个点,有x和y
RNG(int seed) 使用种子seed产生一个64位随机整数,默认-1
RNG::uniform(a, b ) 返回一个[a,b)范围的均匀分布的随机数,a,b的数据类型要一致,而且必须是int、float、double中的一种,默认是int。
RNG::gaussian( σ) 返回一个均值为0,标准差为σ的随机数。如果要产生均值为λ,标准差为σ的随机数,可以λ+ RNG::gaussian( σ)
详细说明
# cmake needs this line
cmake_minimum_required(VERSION 3.1)
# Define project name
project(01)
# Find OpenCV, you may need to set OpenCV_DIR variable
# to the absolute path to the directory containing OpenCVConfig.cmake file
# via the command line or GUI
find_package(OpenCV REQUIRED)
# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS " config: ${OpenCV_DIR}")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
# Declare the executable target built from your sources
add_executable(caiji02 14图像几何形状绘制.cpp)
# Link your application with OpenCV libraries
target_link_libraries(caiji02 PRIVATE ${OpenCV_LIBS})
画出来还是婷好看的
这个函数只能用来绘制多边形,不能填充
void cv::polylines ( Mat & img,
const Point *const * pts,
const int * npts,
int ncontours,
bool isClosed,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0
)
img 作为画布的矩阵
pts 折线顶点数组
npts 折线顶点个数
ncontours 待绘制折线数
isClosed 是否是闭合折线(多边形)
color 折线的颜色
thickness 折线粗细
lineType 线段类型
shift 缩放比例(0是不缩放,4是1/4)
填充多边形
画出图像的轮廓,也可以绘制多边形
void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )
第一个参数image表示目标图像,
第二个参数contours表示输入的轮廓组,每一组轮廓由点vector构成,
第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓,
第四个参数color为轮廓的颜色,
第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,
第六个参数lineType为线型,
第七个参数为轮廓结构信息,
第八个参数为maxLevel
OpenCV中的有关鼠标操作函数,主要是鼠标操作的回调函数static void on_Mouse(int event, int x, int y, int flag, void)*,以及控制是否执行回调函数的函数setMouseCallback(“windowName”, on_Mouse, 0)。
void cv::normalize(InputArry src,InputOutputArray dst,double alpha=1,double beta=0,int norm_type=NORM_L2,int dtype=-1,InputArray mark=noArry())
函数作用: 该函数归一化输入数组使它的范数或者数值范围在一定的范围内。
归一化数据。该函数分为范围归一化与数据值归一化。(Normalizes the norm or value range of an array.)其实范围归一化和数值归一化可以归为一类,一般来说数值归一化是指将数值归一到[0,1]区间上,而范围归一化则指将数值归一到[a,b]上,a,b为任意值。由此看出,数值归一化是范围归一化的特例,包含在范围归一化中。
src 输入数组;
dst 输出数组,数组的大小和原数组一致;
alpha 用来规范值或者规范范围,并且是下限;
beta 只用来规范范围并且是上限,因此只在NORM_MINMAX中起作用;
norm_type 归一化选择的数学公式类型;
dtype 当为负,输出在大小深度通道数都等于输入,当为正,输出只在深度与输如不同,不同 的地方由dtype决定;
mark 掩码。选择感兴趣区域,选定后只能对该区域进行操作。
opencv提供了四种归一化方法,NORM_L1、NORM_INF、NORM_L2,NORM_MINMAX
src.convertTo(dst, type, scale, shift)
链接 https://blog.csdn.net/qq_22764813/article/details/52135686
img参数为图像数据来源,其类型为Mat。
注意也不是所有格式的Mat型数据都能被使用保存为图片,目前OpenCV主要只支持单通道和3通道的图像,并且此时要求其深度为8bit和16bit无符号(即CV_16U),所以其他一些数据类型是不支持的,比如说float型等。
如果Mat类型数据的深度和通道数不满足上面的要求,则需要使用convertTo()函数和cvtColor()函数来进行转换。
convertTo()函数负责转换数据类型不同的Mat,即可以将类似float型的Mat转换到imwrite()函数能够接受的类型。
而cvtColor()函数是负责转换不同通道的Mat,因为该函数的第4个参数就可以设置目的Mat数据的通道数(只是我们一般没有用到它,一般情况下这个函数是用来进行色彩空间转换的)。
另外也可以不用imwrite()函数来存图片数据,可以直接用通用的XML IO接口函数将数据存在XML或者YXML中。
缩放并转换到另外一种数据类型:
dst:目的矩阵;
type:需要的输出矩阵类型,或者更明确的,是输出矩阵的深度,如果是负值(常用-1)则输出矩阵和输入矩阵类型相同;
scale:比例因子;
shift:将输入数组元素按比例缩放后添加的值;
dst(i)=src(i)xscale+(shift,shift,…)
如果scale=1,shift=0,则不进行比例缩放。
如果输入数组与输出数组的类型相同,则函数可以被用于缩放和平移矩阵或图像;
src.convertTo(dst,CV_32F);
转化为float32数据类型
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR)
src - 原图
dst - 目标图像。当参数dsize不为0时,dst的大小为size;否则,它的大小需要根据src的大小,参数fx和fy决定。dst的类型(type)和src图像相同
dsize - 目标图像大小。当dsize为0时,它可以通过以下公式计算得出:
所以,参数dsize和参数(fx, fy)不能够同时为0
fx - 水平轴上的比例因子。当它为0时,计算公式如下:
fy - 垂直轴上的比例因子。当它为0时,计算公式如下:
interpolation - 插值方法。共有5种:
1)INTER_NEAREST - 最近邻插值法
2)INTER_LINEAR - 双线性插值法(默认)
3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。
4)INTER_CUBIC - 基于4x4像素邻域的3次插值法
5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
void flip(InputArray src, OutputArray dst, int flipCode);
flip()函数翻转一个二维的矩阵,包含垂直翻转,水平翻转,以及垂直水平翻转,
flipCode =0,垂直翻转图像,是源图像的top-left(左上)和bottom-left(左下)的交换,也就是说左上变成了左下,左下变成了左上,这是一个典型在的 Microsoft Windows操作系统里的视频处理操作。 上下反转
flipCode > 0,图像的水平翻转,随后的水平位移和绝对方差计算,是为了检查图像是否y轴对称。 左右翻转
(flipCode < 0),图像同时垂直翻转和水平翻转,是为了以后的位移和绝对方差计算去检查图像是否是中心对称。 180度翻转
反转点阵队列的顺序(flipCode > 0 或flipCode == 0).
参数 src 输入矩阵.
参数 dst 输出矩阵,和输入矩阵一样大小。
参数 flipCode 一个标志,决定怎么翻转矩阵; 0 是围绕着x轴翻转,正直是围绕着y轴翻转,负值是围绕着两个轴一起翻转。 around both axes.
获得图像绕着 某一点的旋转矩阵
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
Point2f center:表示旋转的中心点
double angle:表示旋转的角度
double scale:图像缩放因子
参考
void cv::warpAffine ( InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
. src: 输入图像
. dst: 输出图像,尺寸由dsize指定,图像类型与原图像一致
. M: 2X3的变换矩阵
. dsize: 指定图像输出尺寸
. flags: 插值算法标识符,有默认值INTER_LINEAR,如果插值算法为WARP_INVERSE_MAP, warpAffine函数使用如下矩阵进行图像转换
C++: VideoCapture::VideoCapture();
C++: VideoCapture::VideoCapture(const string& filename);
C++: VideoCapture::VideoCapture(int device);
功能:创建一个VideoCapture类的实例,如果传入对应的参数,可以直接打开视频文件或者要调用的摄像头。
参数:
filename – 打开的视频文件名。
device – 打开的视频捕获设备id ,如果只有一个摄像头可以填0,表示打开默认的摄像头
open(const string& filename, int fourcc, double fps, Size frameSize, bool isColor=true)
filename:保存视频的路径名
fourcc:录制视频的格式
OpenCV提供的格式是未经过压缩的,个人感觉录制的视频是有损失的,没有原视频效果好,目前支持的格式如下:
CV_FOURCC(‘P’, ‘I’, ‘M’, ‘1’) = MPEG-1 codec
CV_FOURCC(‘M’, ‘J’, ‘P’, ‘G’) = motion-jpeg codec
CV_FOURCC(‘M’, ‘P’, ‘4’, ‘2’) = MPEG-4.2 codec
CV_FOURCC(‘D’, ‘I’, ‘V’, ‘3’) = MPEG-4.3 codec
CV_FOURCC(‘D’, ‘I’, ‘V’, ‘X’) = MPEG-4 codec
CV_FOURCC(‘U’, ‘2’, ‘6’, ‘3’) = H263 codec
CV_FOURCC(‘I’, ‘2’, ‘6’, ‘3’) = H263I codec
CV_FOURCC(‘F’, ‘L’, ‘V’, ‘1’) = FLV1 codec
fps:录制视频的帧率(1秒多少帧)
frameSize:录制视频图片的尺寸大小(需要跟原图像保持一致)
isColor:bool类型的,一般默认为true,彩色
录制视频 m_SkyWrite.write(frame);
释放对象 m_SkyWrite.release();
void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )
onst Mat* images:输入图像
int nimages:输入图像的个数
const int* channels:需要统计直方图的第几通道
InputArray mask:掩膜,,计算掩膜内的直方图 …Mat()
OutputArray hist:输出的直方图数组
int dims:需要统计直方图通道的个数
const int* histSize:指的是直方图分成多少个区间,就是 bin的个数
const float** ranges: 统计像素值得区间
bool uniform=true::是否对得到的直方图数组进行归一化处理
bool accumulate=false:在多个图像时,是否累计计算像素值得个数
void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
. InputArray src: 输入图像,可以是Mat类型,图像深度是CV_8U、CV_16U、CV_16S、CV_32F以及CV_64F其中的某一个。
. OutputArray dst: 输出图像,深度和类型与输入图像一致
. Size ksize: 滤波模板kernel的尺寸,一般使用Size(w, h)来指定,如Size(3,3)
. Point anchor=Point(-1, -1): 字面意思是锚点,也就是处理的像素位于kernel的什么位置,默认值为(-1, -1)即位于kernel中心点,如果没有特殊需要则不需要更改
. int borderType=BORDER_DEFAULT: 用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT);
src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
ksize,高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数(并不能理解)。或者,它们可以是零的,它们都是由sigma计算而来。
sigmaX,表示高斯核函数在X方向的的标准偏差。
sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。
中值滤波
medianBlur(image, median_blur_image, 3)
第一和第二个参数分别是输入和输出图像,第三个参数就是移动窗口的大小,注意这个ksize参数必须为奇数,这是该函数参数规定的,如果传入值不是奇数的话就会报错,应该是为了便于找到窗口的中心位置。
直方图均衡化
将输入图像进行直方图均衡化操作后输出一幅新图像,要注意的是,这里的输入图像只可以输入单通道图像,所以我们对三通道图像进行直方图均衡化时,需要先将其分离成三幅单通道的图像,再分别进行处理,随后再将输出的三幅单通道图像合成起来,这才最终完成对三通道图像的直方图均衡化操作。如果是单通道的图像,就可以直接使用这个API来进行操作。
a.先用cvtColor()把图像从RGB色彩空间转换到HSV色彩空间;
b.计算图像的直方图,然后归一化到[0~1]之间,用到函数 calcHist() 和 normalize() ;
c.使用上述的四种方法之一进行比较,用到函数compareHist()。
函数一共有三个参数,一个输入图像,一个输出图像,一个比较方法。比较方法的取值的情况为上面的四种方法,在OpenCV中,每个都有自己的名字:Correlation ( CV_COMP_CORREL );Chi-Square ( CV_COMP_CHISQR );Intersection ( CV_COMP_INTERSECT );Bhattacharyya 距离( CV_COMP_BHATTACHARYYA )。
反向投影
calcBackProject(&test_image_hsv, 1, channels, hist_model, backProject, HistRanges)
第一个参数是要进行投影的输入图像的地址,注意该API要求输入的是地址;
第二个参数是输入图像的数目;
第三个参数是要进行投影的通道数;
第四个参数是输入模板的直方图;
第五个参数是输出的反向投影结果,为一个Mat对象;
第六个参数是输入模板直方图的通道取值范围的地址的地址,也就是上面定义的HistRanges;
再往后的两个参数使用默认值即可。
在图像中利用选取的区域邻域,来修复该区域
void inpaint(
InputArray src, // 表示要修复的图像,8位三通道或三通道
InputArray inpaintMask, // 表示修复模板(掩模),8位单通道,非零区域为修补区域
OutputArray dst, // 表示修复后的图像
double inpaintRadius, // 表示该算法所考虑的需要修补的每个点的圆形邻域的圆形领域半径。
int flags // 表示修复使用的算法
// CV_INPAINT_TELEA Alexandru Telea 算法 .
// CV_INPAINT_NS 基于 Navier-Stokes 方程的算法
);
高斯双边模糊:不仅考虑空间分布权重,同时考虑像素值分布权重,将像素值差异过大的区域(即边缘)进行保留。
bilateralFilter(test_image, bila_image, 0, 100, 10, 4)
第一个参数:需要进行处理的输入图像;
第二个参数:处理完成后的输出图像;
第三个参数d: 表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace来计算该值。官方文档中推荐对于实时处理中建议值为d=5;非实时建议d=9;也可以直接设置为0,由sigmaSpace来自行计算。该参数设置越大,效果更好但是速度会非常慢。
第四和第五个参数sigmaColor和sigmaSpace:当小于10时对滤波器影响很小,当大于150时会使图像变得卡通化;sigmaColor可以设置稍大,越大表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域;sigmaSpace可设置偏小(>=10),使运行速度提高,如果参数d为0,则参数d跟sigmaSpace成正比。
均值迁移模糊
首先仍然会使用两个窗口,一个是物理空间窗口,一个是色彩空间窗口,利用物理空间窗口内的元素去进行均值计算得到梯度dx和dy,利用色彩空间窗口内的元素进行均值计算得到新的RGB值,然后通过dx和dy得到物理窗口需要移动的方向和距离,并进行窗口迁移;在迁移到新的物理空间窗口后,同样计算梯度dx和dy,并在新的色彩空间计算RGB值。通过不断的迁移,直到满足了设定好的停止条件,就停止窗口迁移,并把最终的RGB值赋给中心像素点。
均值迁移模糊属于图像在色彩层面的平滑滤波,可以中和色彩分布相近的颜色,平滑色彩细节,侵蚀掉面积较小的颜色区域,同样具有边缘保留效果。经常用在对图像进行分水岭分割操作之前的降噪过程,可以大幅度提升分水岭分割的效果。
void cvPyrMeanShiftFiltering( const CvArr* src, CvArr* dst,
double sp, double sr, int max_level=1,
CvTermCriteria termcrit=cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,5,1));
第一个参数:需要处理的输入图像;
第二个参数:处理完成的输出图像;
第三个参数sp:定义的迁移物理空间半径大小;
第四个参数sr:定义的迁移色彩空间半径大小;
关键参数是sp和sr的设置,二者设置的值越大,对图像色彩的平滑效果越明显,同时函数耗时也越多
最后两个参数分别为金字塔层数、迭代终止条件,使用default值即可。
边缘保护滤波
void edgePreservingFilter( InputArray src, OutputArray dst, int flags = 1,
float sigma_s = 60, float sigma_r = 0.4f);
src: 输入 8 位 3 通道图像。
dst: 输出 8 位 3 通道图像。
flags: 边缘保护滤波 可选的滤波器类型,OpenCV中提供了两种滤波器:RECURS_FILTER(递归滤波器)和NORMCONV_FILTER(归一化 卷积滤波器),分别的flag为1和2;
sigma_s:取值范围为 0~200。
sigma_r:取值范围为 0~1。
当sigma_s 取值不变时候,sigma_r 越大图像滤波效果越明显;
当sigma_r 取值不变时候,窗口 sigma_s 越大图像模糊效果越明显;
当sgma_r取值很小的时候,窗口 sigma_s 取值无论如何变化,图像双边滤波效果都不好!
非局部平均去噪
fastNlMeansDenoising() - 使用单个灰度图像
fastNlMeansDenoisingColored() - 使用彩色图像。
fastNlMeansDenoisingMulti() - 用于在短时间内捕获的图像序列(灰度图像)
fastNlMeansDenoisingColoredMulti() - 与上面相同,但用于彩色图像。
fastNlMeansDenoisingColored( InputArray src, OutputArray dst,
float h = 3, float hColor = 3,
int templateWindowSize = 7, int searchWindowSize = 21)