皓月孤辰:本文存在相当大比例来源于其他人的文章,但是里面的每个函数自己都是一点点验证过的,并写出了使用的例子和自己整理的函数,不确定算转载还是算原创,算转载吧,并不是一个人的功劳,算原创吧,不是我一个人的功劳,最后权衡还是注明了原创,希望使用的朋友别骂我,谢谢。
注明:①本文学习顺序内容来自于浅墨_毛星云,其余的是本人根据自己的理解和搜集所整理,opencv的配置可以看这位爱学习的李二哈同学啊
②本人写这篇时使用的是VS2019+Qt5.12–MSVC2017+OpenCV4.5.4
③本文更适合已经学过了的再使用,相当于遗忘了再点进来回忆一下而已。
以filename为路径的图像载入
Mat imread(const string& filename, int flags=1 );
例子:
Mat image = imread("D:/My_Work/Gold.jpg");
第一个参数,const string&类型的filename,填我们需要载入的图片路径名;
第二个参数,int类型的flags,为载入标识,它指定一个加载图像的颜色类型。
enum ImreadModes {
IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation.
IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
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.
};
新建winname名的窗口,切记!name后面有个d!很容易打漏
void namedWindow(const string& winname,int flags=WINDOW_AUTOSIZE );
例子:
namedWindow("King");
第一个参数,const string&型的name,即填被用作窗口的标识符的窗口名称。
第二个参数,int 类型的flags ,窗口的标识,可以填如下的值:
WINDOW_NORMAL设置了这个值,用户便可以改变窗口的大小(没有限制)
WINDOW_AUTOSIZE如果设置了这个值,窗口大小会自动调整以适应所显示的图像,并且不能手动改变窗口大小。
WINDOW_OPENGL 如果设置了这个值的话,窗口创建的时候便会支持OpenGL。
enum WindowFlags {
WINDOW_NORMAL = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size.
WINDOW_AUTOSIZE = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed.
WINDOW_OPENGL = 0x00001000, //!< window with opengl support.
WINDOW_FULLSCREEN = 1, //!< change the window to fullscreen.
WINDOW_FREERATIO = 0x00000100, //!< the image expends as much as it can (no ratio constraint).
WINDOW_KEEPRATIO = 0x00000000, //!< the ratio of the image is respected.
WINDOW_GUI_EXPANDED=0x00000000, //!< status bar and tool bar
WINDOW_GUI_NORMAL = 0x00000010, //!< old fashious way
};
在以winname为名的窗口展示mat图片
void imshow(const string& winname, InputArray mat);
例子:
imshow("King", image);
第一个参数,const string&类型的winname,填需要显示的窗口标识名称。
第二个参数,InputArray 类型的mat,填需要显示的图像。
imshow 函数详解:
imshow 函数用于在指定的窗口中显示图像。如果窗口是用CV_WINDOW_AUTOSIZE(默认值)标志创建的,那么显示图像原始大小。否则,将图像进行缩放以适合窗口。而imshow 函数缩放图像,取决于图像的深度:
如果载入的图像是8位无符号类型(8-bit unsigned),就显示图像本来的样子。
如果图像是16位无符号类型(16-bit unsigned)或32位整型(32-bit integer),便用像素值除以256。也就是说,值的范围是[0,255 x 256]映射到[0,255]。
如果图像是32位浮点型(32-bit floating-point),像素值便要乘以255。也就是说,该值的范围是[0,1]映射到[0,255]。
关闭imshow对应的窗口名
void destroyWindow(const String& winname);
//关闭所有OpenCv的窗口
void destroyAllWindow();
例子:
destroyWindow("King");
winname是上一个函数的窗口名。
输出图像到文件,我们一般都用imwrite函数
bool imwrite(const string& filename,InputArray img, const vector<int>& params=vector<int>() );
例子:
vector<int> compression_params;
compression_params.push_back( CV_IMWRITE_JPEG_QUALITY); //选择jpeg
compression_params.push_back( 100); //在这个填入你要的图片质量
imwrite( "test2.jpg", img, compression_params);
第一个参数,const string&类型的filename,填需要写入的文件名就行了,带上后缀,比如,“123.jpg”这样。
第二个参数,InputArray类型的img,一般填一个Mat类型的图像数据就行了。
第三个参数,const vector&类型的params,表示为特定格式保存的参数编码,具体参数可看cv::ImwriteFlags,它有默认值vector(),所以一般情况下不需要填写。而如果要填写的话,有下面这些需要了解的地方:
对于JPEG格式的图片,这个参数表示从0到100的图片质量(CV_IMWRITE_JPEG_QUALITY),默认值是95.
对于PNG格式的图片,这个参数表示压缩级别(CV_IMWRITE_PNG_COMPRESSION)从0到9。较高的值意味着更小的尺寸和更长的压缩时间,而默认值是3。
对于PPM,PGM,或PBM格式的图片,这个参数表示一个二进制格式标志(CV_IMWRITE_PXM_BINARY),取值为0或1,而默认值是1。
版本不同,参数也有变化
enum ImwriteFlags {
IMWRITE_JPEG_QUALITY = 1, //!< For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default value is 95.
IMWRITE_JPEG_PROGRESSIVE = 2, //!< Enable JPEG features, 0 or 1, default is False.
IMWRITE_JPEG_OPTIMIZE = 3, //!< Enable JPEG features, 0 or 1, default is False.
IMWRITE_JPEG_RST_INTERVAL = 4, //!< JPEG restart interval, 0 - 65535, default is 0 - no restart.
IMWRITE_JPEG_LUMA_QUALITY = 5, //!< Separate luma quality level, 0 - 100, default is 0 - don't use.
IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< Separate chroma quality level, 0 - 100, default is 0 - don't use.
IMWRITE_PNG_COMPRESSION = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. If specified, strategy is changed to IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY). Default value is 1 (best speed setting).
IMWRITE_PNG_STRATEGY = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE.
IMWRITE_PNG_BILEVEL = 18, //!< Binary level PNG, 0 or 1, default is 0.
IMWRITE_PXM_BINARY = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1.
IMWRITE_EXR_TYPE = (3 << 4) + 0, /* 48 */ //!< override EXR storage type (FLOAT (FP32) is default)
IMWRITE_EXR_COMPRESSION = (3 << 4) + 1, /* 49 */ //!< override EXR compression type (ZIP_COMPRESSION = 3 is default)
IMWRITE_WEBP_QUALITY = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used.
IMWRITE_PAM_TUPLETYPE = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format
IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set; see libtiff documentation for valid values
IMWRITE_TIFF_XDPI = 257,//!< For TIFF, use to specify the X direction DPI
IMWRITE_TIFF_YDPI = 258, //!< For TIFF, use to specify the Y direction DPI
IMWRITE_TIFF_COMPRESSION = 259, //!< For TIFF, use to specify the image compression scheme. See libtiff for integer constants corresponding to compression formats. Note, for images whose depth is CV_32F, only libtiff's SGILOG compression scheme is used. For other supported depths, the compression scheme can be specified by this flag; LZW compression is the default.
IMWRITE_JPEG2000_COMPRESSION_X1000 = 272 //!< For JPEG2000, use to specify the target compression rate (multiplied by 1000). The value can be from 0 to 1000. Default is 1000.
};
将img2赋值到roi中,并加载一个掩膜。
Mat mask(roi.rows,roi.cols,roi.depth(),Scalar(1));
img2.copyTo(roi,mask);
ROI区域相当于引用一般,赋值ROI的右值所属就是主Mat。
方法一,以像素坐标系为基础,左上角为原点
Mat image;
Mat logo = imread("1.jpg");
//定义一个Mat类型并给其设定ROI区域
Mat imageROI;
//方法一
imageROI = image( Rect( 500, 250, logo.cols, logo.rows));
//cols: Mat的列索引,即宽度;
//rows: Mat的行索引,即高度;
Rect( x坐标值, y坐标值, logo 的宽, logo的高);
方法二:以索引为依据去设置ROI区域
//方法二
imageROI = srcImage3(Range( 250, 250+logoImage.rows), Range( 200, 200+logoImage.cols));
//y起点:250,y终点:250+logoImage的行索引
//x起点:200,x终点:200+logoImage的列索引
//即Rect( 200, 250, logoImage.cols, logoImage.rows);
Range( 起始索引, 终止索引);
void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
例子:
cvtColor(image, imageGray, COLOR_BGR2GRAY); //转灰度图
cvtColor(image, imageHsv, COLOR_BGR2HSV); //转HSV图
将输入的图像呈现成非thresh即maxval的值
double threshold( InputArray src, OutputArray dst,double thresh, double maxval, int type );
例子:
threshold(image, imageBinary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
第一个参数,InputArray类型的src,输入数组,填单通道 , 8或32位浮点类型的Mat即可。
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放输出结果,且和第一个参数中的Mat变量有一样的尺寸和类型。
第三个参数,double类型的thresh,阈值的具体值。
第四个参数,double类型的maxval,当第五个参数阈值类型type取 CV_THRESH_BINARY 或CV_THRESH_BINARY_INV 阈值类型时的最大值.
第五个参数,int类型的type,阈值类型,。threshold( )函数支持的对图像取阈值的方法由其确定
//! type of the threshold operation
//! ![threshold types](pics/threshold.png)
enum ThresholdTypes {
THRESH_BINARY = 0, //!< \f[\texttt{dst} (x,y) = \fork{\texttt{maxval}}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{0}{otherwise}\f]
THRESH_BINARY_INV = 1, //!< \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{maxval}}{otherwise}\f]
THRESH_TRUNC = 2, //!< \f[\texttt{dst} (x,y) = \fork{\texttt{threshold}}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f]
THRESH_TOZERO = 3, //!< \f[\texttt{dst} (x,y) = \fork{\texttt{src}(x,y)}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{0}{otherwise}\f]
THRESH_TOZERO_INV = 4, //!< \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f]
THRESH_MASK = 7,
THRESH_OTSU = 8, //!< flag, use Otsu algorithm to choose the optimal threshold value
THRESH_TRIANGLE = 16 //!< flag, use Triangle algorithm to choose the optimal threshold value
};
inline
void GpuMat::create(Size size_, int type_)
{
create(size_.height, size_.width, type_);
}
例子:
dst.create( src1.size(), src1.type() );
template<typename _Tp> inline
Scalar_<_Tp> Scalar_<_Tp>::all(_Tp v0)
{
return Scalar_<_Tp>(v0, v0, v0, v0);
}
例子:
dst = Scalar::all(0);
返回跟参数最接近的整数值,即四舍五入;
int cvRound( double value )
int cvRound( float value )
int cvRound( int value )
例子:
cvRound(3.7) == 4
cvRound(-3.7) == -4
返回不大于参数的最大整数值,即向下取整;
int cvFloor( double value )
int cvFloor( float value )
int cvFloor( int value )
例子:
cvFloor(3.7) == 3
cvFloor(-3.7) == -4
返回不小于参数的最小整数值,即向上取整;
int cvCeil( double value )
int cvCeil( float value )
int cvCeil( int value )
例子:
cvCeil(3.7) == 4
cvCeil(-3.7) == -3
int waitKey(int delay = 0);
例子:
//按任意键关闭窗口,
image.waitKey(0)
//延时一秒关闭窗口
image.waitKey(1000)
delay参数:delay延迟毫秒。 0是表示“永远”的特殊值。
返回值: ASCII码的值,根据按键对应在ASCII里的值,即可知道限制返回多少,如ESC是27,空格是32。
.
typedef struct Scalar
{
double val[4];
}Scalar;
例子:
Mat M(7,7,CV_32FC2,Scalar(1,3));
上面的代码表示:创建一个2通道,且每个通道的值都为(1,3),深度为32,7行7列的图像矩阵。CV_32F表示每个元素的值的类型为32位浮点数,C2表示通道数为2,Scalar(1,3)表示对矩阵每个元素都赋值为(1,3),第一个通道中的值都是1,第二个通道中的值都是3.
Mat blue_m(256,256,CV_8UC3,Scalar(255,0,0));
这里的Scalar的值代表着三通道中的BGR颜色值,注意并不是RGB顺序
typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<ushort, 2> Vec2w;
typedef Vec<ushort, 3> Vec3w;
typedef Vec<ushort, 4> Vec4w;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<int, 6> Vec6i;
typedef Vec<int, 8> Vec8i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;
例子:
vector<Vec2f> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合
//依次在图中绘制出每条线段
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line( dstImage, pt1, pt2, Scalar(55,100,195), 1, CV_AA);
}
固定向量别名命名规则:
cv::Vec{2,3,4,6}{b, s ,w , i, f, d}
{2,3,4,6}代表向量的长度。
{b, s ,w , i, f, d}表示向量内数据类型。
b:unsigned char ; s:short int
w:unsigned short; i:int
f:float; d:double
#define CV_8U 0
#define CV_8S 1
#define CV_16U 2
#define CV_16S 3
#define CV_32S 4
#define CV_32F 5
#define CV_64F 6
#define CV_16F 7
#define CV_PI 3.1415926535897932384626433832795
#define CV_2PI 6.283185307179586476925286766559
#define CV_LOG2 0.69314718055994530941723212145818
计算两个数组(图像阵列Mat)的加权和,并加载到输出阵列中,实现线性混合
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1);
例子:
//dst = src1[I]*alpha+ src2[I]*beta + gamma;
addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);
第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。
第二个参数,alpha,表示第一个数组的权重
第三个参数,src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。
第四个参数,beta,表示第二个数组的权重值。
第五个参数,dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。
第六个参数,gamma,一个加到权重总和上的标量值。看下面的式子自然会理解。
第七个参数,dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。
将多通道分割成几个单通道,三通道的会分成蓝绿红,有两种:
C++: void split(const Mat& src, Mat*mvbegin);
C++: void split(InputArray m,OutputArrayOfArrays mv);
例子:
Mat outImage[3];
split( image, Mat *或者Vector< Mat>);
输入Mat格式的图像,输出数组或者Vector的。
反向split
C++: void merge(const Mat* mv, size_tcount, OutputArray dst)
C++: void merge(InputArrayOfArrays mv,OutputArray dst)
例子:
merge(matArray,3,dst);
merge(matVector,dst);
C++: int createTrackbar(conststring& trackbarname, conststring& winname,
int* value, int count, TrackbarCallback onChange=0,void* userdata=0);
第一个参数,const string&类型的trackbarname,表示轨迹条的名字,用来代表我们创建的轨迹条。
第二个参数,const string&类型的winname,填窗口的名字,表示这个轨迹条会依附到哪个窗口上,即对应namedWindow()创建窗口时填的某一个窗口名。
第三个参数,int* 类型的value,一个指向整型的指针,表示滑块的位置。并且在创建时,滑块的初始位置就是该变量当前的值。
第四个参数,int类型的count,表示滑块可以达到的最大位置的值。PS:滑块最小的位置的值始终为0。
第五个参数,TrackbarCallback类型的onChange,首先注意他有默认值0。这是一个指向回调函数的指针,每次滑块位置改变时,这个函数都会进行回调。并且这个函数的原型必须为void XXXX(int pos ,void* userdata);其中第一个参数是轨迹条的位置,第二个参数是用户数据(看下面的第六个参数)。如果回调是NULL指针,表示没有回调函数的调用,仅第三个参数value有变化。
第六个参数,void*类型的userdata,他也有默认值0。这个参数是用户传给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value实参是全局变量的话,完全可以不去管这个userdata参数。
这个函数用于获取当前轨迹条的位置并返回。
C++: int getTrackbarPos(conststring& trackbarname, conststring& winname);
第一个参数,const string&类型的trackbarname,表示轨迹条的名字。
第二个参数,const string&类型的winname,表示轨迹条的父窗口的名称。
emap( )函数会根据我们指定的映射形式,将源图像进行重映射几何变换,基于的式子如下:
dst(x,y) = src( mapx(x,y), mapy(x,y))
C++: void remap(InputArray src,
OutputArraydst,
InputArray map1,
InputArray map2,
int interpolation,
intborderMode=BORDER_CONSTANT,
const Scalar& borderValue=Scalar())
例子:
//【2】创建和原始图一样的效果图,x重映射图,y重映射图
dstImage.create( srcImage.size(), srcImage.type() );
map_x.create( srcImage.size(), CV_32FC1 );
map_y.create( srcImage.size(), CV_32FC1 );
//【3】双层循环,遍历每一个像素点,改变map_x & map_y的值
for( int j = 0; j < srcImage.rows;j++)
{
for( int i = 0; i < srcImage.cols;i++)
{
//改变map_x & map_y的值.
map_x.at<float>(j,i) = static_cast<float>(i);
map_y.at<float>(j,i) = static_cast<float>(srcImage.rows - j);
}
}
//【4】进行重映射操作
remap( srcImage, dstImage, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );
src:输入图像,灰度图或真彩图均可。
dst:输出图像,要求大小和xmap,ymap相同,通道数目及数据类型和src相同。
xmap:用于存放图像X方向的映射关系,类型必须是CV_32FC1的,它有两种可能的表示对象。
1.表示点(x,y)的第一个映射。
2.表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值。
ymap:用于存放图像Y方向的映射关系,类型必须是CV_32FC1的,同样,它也有两种可能的表示对象,而且他是根据map1来确定表示那种对象。
1.若map1表示点(x,y)时。这个参数不代表任何值。
2.表示CV_16UC1 , CV_32FC1类型的Y值(第二个值)。
interpolation:插值方式如下方代码所示,其中常用的如下。
INTER_NEAREST - 最近邻插值
INTER_LINEAR – 双线性插值(默认值)
INTER_CUBIC – 双三次样条插值(逾4×4像素邻域内的双三次插值)
INTER_LANCZOS4 -Lanczos插值(逾8×8像素邻域的Lanczos插值)
borderMode:图像边界处理方式,边界的类型有以下几种:
1)BORDER_REPLICATE:重复: aaaaaa|abcdefgh|hhhhhhh
2)BORDER_REFLECT:反射: fedcba|abcdefgh|hgfedcb
3)BORDER_REFLECT_101:反射101: gfedcb|abcdefgh|gfedcba
4)BORDER_WRAP:外包装: cdefgh|abcdefgh|abcdefg
5)BORDER_CONSTANT:常量复制: iiiiii|abcdefgh|iiiiiii(i的值由后一个参数Scalar()确定,如Scalar::all(0) )
borderValue:若上一参数为BORDER_CONSTANT,则由此参数确定补充上去的像素值。可选用默认值。
//! interpolation algorithm
enum InterpolationFlags{
/** nearest neighbor interpolation */
INTER_NEAREST = 0,
/** bilinear interpolation */
INTER_LINEAR = 1,
/** bicubic interpolation */
INTER_CUBIC = 2,
/** resampling using pixel area relation. It may be a preferred method for image decimation, as
it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST
method. */
INTER_AREA = 3,
/** Lanczos interpolation over 8x8 neighborhood */
INTER_LANCZOS4 = 4,
/** Bit exact bilinear interpolation */
INTER_LINEAR_EXACT = 5,
/** Bit exact nearest neighbor interpolation. This will produce same results as
the nearest neighbor method in PIL, scikit-image or Matlab. */
INTER_NEAREST_EXACT = 6,
/** mask for interpolation codes */
INTER_MAX = 7,
/** flag, fills all of the destination image pixels. If some of them correspond to outliers in the
source image, they are set to zero */
WARP_FILL_OUTLIERS = 8,
/** flag, inverse transformation
For example, #linearPolar or #logPolar transforms:
- flag is __not__ set: \f$dst( \rho , \phi ) = src(x,y)\f$
- flag is set: \f$dst(x,y) = src( \rho , \phi )\f$
*/
WARP_INVERSE_MAP = 16
};
计算二维旋转变换矩阵。变换会将旋转中心映射到它自身。
C++: Mat getRotationMatrix2D(Point2fcenter, double angle, double scale)
例子:
//定义两组点,代表两个三角形
Point2f srcTriangle[3];
Point2f dstTriangle[3];
//设置源图像和目标图像上的三组点以计算仿射变换
srcTriangle[0] = Point2f( 0,0 );
srcTriangle[1] = Point2f( static_cast<float>(srcImage.cols - 1), 0 );
srcTriangle[2] = Point2f( 0, static_cast<float>(srcImage.rows - 1 ));
dstTriangle[0] = Point2f( static_cast<float>(srcImage.cols*0.0), static_cast<float>(srcImage.rows*0.33));
dstTriangle[1] = Point2f( static_cast<float>(srcImage.cols*0.65), static_cast<float>(srcImage.rows*0.35));
dstTriangle[2] = Point2f( static_cast<float>(srcImage.cols*0.15), static_cast<float>(srcImage.rows*0.6));
//求得仿射变换
warpMat = getAffineTransform( srcTriangle, dstTriangle );
第一个参数,Point2f类型的center,表示源图像的旋转中心。
第二个参数,double类型的angle,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。
第三个参数,double类型的scale,缩放系数。
warpAffine函数的作用是依据如下式子,对图像做仿射变换。
C++: void warpAffine(InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags=INTER_LINEAR,
intborderMode=BORDER_CONSTANT,
const Scalar& borderValue=Scalar())
例子:
//对源图像应用刚刚求得的仿射变换 image与image2同规格, warpMat看上一条
warpAffine( image, image2, warpMat, image2.size() )
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,需和源图片有一样的尺寸和类型。
第三个参数,InputArray类型的M,2×3的变换矩阵。
第四个参数,Size类型的dsize,表示输出图像的尺寸。
第五个参数,int类型的flags,插值方法的标识符。此参数有默认值
INTER_LINEAR(线性插值),可选的插值方式如下:
INTER_NEAREST - 最近邻插值
INTER_LINEAR - 线性插值(默认值)
INTER_AREA - 区域插值
INTER_CUBIC –三次样条插值
INTER_LANCZOS4 -Lanczos插值
CV_WARP_FILL_OUTLIERS - 填充所有输出图像的象素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval.
CV_WARP_INVERSE_MAP –表示M为输出图像到输入图像的反变换,即 。因此可以直接用来做象素插值。否则, warpAffine函数从M矩阵得到反变换。
第六个参数,int类型的borderMode,边界像素模式,默认值为BORDER_CONSTANT。
第七个参数,const Scalar&类型的borderValue,在恒定的边界情况下取的值,默认值为Scalar(),即0。
ps:另外提一点,我们的WarpAffine函数与一个叫做cvGetQuadrangleSubPix( )的函数类似,但是不完全相同。 WarpAffine要求输入和输出图像具有同样的数据类型,有更大的资源开销(因此对小图像不太合适)而且输出图像的部分可以保留不变。而 cvGetQuadrangleSubPix 可以精确地从8位图像中提取四边形到浮点数缓存区中,具有比较小的系统开销,而且总是全部改变输出图像的内容。
boxFilter的函数作用是使用方框滤波(box filter)来模糊一张图片,由src输入,dst输出。
C++: void boxFilter(InputArray src,OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), boolnormalize=true, int borderType=BORDER_DEFAULT );
例子:
//载入原图
Mat image=imread("2.jpg");
//进行均值滤波操作
Mat out;
boxFilter(image, out, -1,Size(5, 5));
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的ddepth,输出图像的深度,-1代表使用原图深度,即src.depth()。
第四个参数,Size类型的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
第五个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
第六个参数,bool类型的normalize,默认值为true,一个标识符,表示内核是否被其区域归一化(normalized)了。
第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。
blur的作用是对输入的图像src进行均值滤波后用dst输出。领域模板均值替换核
C++: void blur(InputArray src, OutputArraydst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT );
例子:
//载入原图
Mat image=imread("1.jpg");
//进行均值滤波操作
Mat out;
blur(image, out, Size(7, 7));
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
第三个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
第四个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
第五个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。
GaussianBlur函数的作用是用高斯滤波器来模糊一张图片,对输入的图像src进行高斯滤波后用dst输出。实际上进行加权平均卷积。
C++: void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT );
例子:
//载入原图
Mat image=imread("1.jpg");
//进行滤波操作
Mat out;
GaussianBlur( image, out, Size( 5, 5 ), 0, 0 );
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
第三个参数,Size类型的ksize高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数。或者,它们可以是零的,它们都是由sigma计算而来。
第四个参数,double类型的sigmaX,表示高斯核函数在X方向的的标准偏差。
第五个参数,double类型的sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。
为了结果的正确性着想,最好是把第三个参数Size,第四个参数sigmaX和第五个参数sigmaY全部指定到。
第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
medianBlur函数使用中值滤波器来平滑(模糊)处理一张图片,从src输入,而结果从dst输出。领域选择中值替换核
且对于多通道图片,每一个通道都单独进行处理,并且支持就地操作(In-placeoperation)。
C++: void medianBlur(InputArray src,OutputArray dst, int ksize)
例子:
//载入原图
Mat image=imread("1.jpg");
//进行中值滤波操作
Mat out;
medianBlur( image, out, 7);
第一个参数,InputArray类型的src,函数的输入参数,填1、3或者4通道的Mat类型的图像;当ksize为3或者5的时候,图像深度需为CV_8U,CV_16U,或CV_32F其中之一,而对于较大孔径尺寸的图片,它只能是CV_8U。
第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。我们可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
第三个参数,int类型的ksize,孔径的线性尺寸(aperture linear size),注意这个参数必须是大于1的奇数,比如:3,5,7,9 …
用双边滤波器来处理一张图片,由src输入图片,结果于dst输出。
C++: void bilateralFilter(InputArray src, OutputArraydst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)
例子:
//载入原图
Mat image=imread("1.jpg");
//进行双边滤波操作
Mat out;
bilateralFilter( image, out, 25, 25*2, 25/2 );
第一个参数,InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
第四个参数,double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
第五个参数,double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
注:腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。
getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)
Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
例子:
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
第一个参数,表示内核的形状,我们可以选择如下三种形状之一:
矩形: MORPH_RECT
交叉形: MORPH_CROSS
椭圆形: MORPH_ELLIPSE
第二个参数,Size类型内核的尺寸,需是正数和奇数
第三个参数,Point类型锚点的位置
dilate函数使用像素邻域内的局部极大运算符来膨胀一张图片,从src输入,由dst输出。支持就地(in-place)操作。
C++: void dilate(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);
例子:
dilate(image, outImage, element);
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
第三个参数,InputArray类型的kernel,膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。
第四个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
第五个参数,int类型的iterations,迭代使用erode()函数的次数,默认值为1。
第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
第七个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。
erode函数使用像素邻域内的局部极小运算符来腐蚀一张图片,从src输入,由dst输出。支持就地(in-place)操作。
注:dilate和erode函数其实都是调用的morphOp函数,只是标识符不同而已
C++: void erode(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);
例子:
erode(image, outImage, element);
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
第三个参数,InputArray类型的kernel,腐蚀操作的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。
第四个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于单位(element)的中心,我们一般不用管它。
第五个参数,int类型的iterations,迭代使用erode()函数的次数,默认值为1。
第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
第七个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。
morphologyEx函数利用基本的膨胀和腐蚀技术,来执行更加高级形态学变换,如开闭运算,形态学梯度,“顶帽”、“黑帽”
C++: void morphologyEx(
InputArray src,
OutputArray dst,
int op,
InputArraykernel,
Pointanchor=Point(-1,-1),
intiterations=1,
intborderType=BORDER_CONSTANT,
constScalar& borderValue=morphologyDefaultBorderValue() );
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的op,表示形态学运算的类型,可以是如下之一的标识符:
MORPH_ERODE = 0, 腐蚀
MORPH_DILATE 膨胀
MORPH_OPEN – 开运算(Opening operation)
MORPH_CLOSE – 闭运算(Closing operation)
MORPH_GRADIENT -形态学梯度(Morphological gradient)
MORPH_TOPHAT - “顶帽”(“Top hat”)
MORPH_BLACKHAT - “黑帽”(“Black hat“)
MORPH_HITMISS = 7 击中击不中变换
第四个参数,InputArray类型的kernel,形态学运算的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们一般使用函数
getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。
第五个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。
其中的这些操作都可以进行就地(in-place)操作。且对于多通道图像,每一个通道都是单独进行操作。
switch( op )
{
case MORPH_ERODE:
erode( src, dst, kernel, anchor, iterations, borderType, borderValue );
break;
case MORPH_DILATE:
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
break;
case MORPH_OPEN:
erode( src, dst, kernel, anchor, iterations, borderType, borderValue );
dilate( dst, dst, kernel, anchor, iterations, borderType, borderValue );
break;
case CV_MOP_CLOSE:
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
erode( dst, dst, kernel, anchor, iterations, borderType, borderValue );
break;
case CV_MOP_GRADIENT:
erode( src, temp, kernel, anchor, iterations, borderType, borderValue );
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
dst -= temp;
break;
case CV_MOP_TOPHAT:
if( src.data != dst.data )
temp = dst;
erode( src, temp, kernel, anchor, iterations, borderType, borderValue );
dilate( temp, temp, kernel, anchor,iterations, borderType, borderValue );
dst = src - temp;
break;
case CV_MOP_BLACKHAT:
if( src.data != dst.data )
temp = dst;
dilate( src, temp, kernel, anchor, iterations, borderType, borderValue);
erode( temp, temp, kernel, anchor, iterations, borderType, borderValue);
dst = temp - src;
break;
Canny函数利用Canny算子来进行图像的边缘检测。产生的边缘很细,可能就一个像素那么细,没有强弱之分。
C++: void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false )
例子:
//载入原始图
Mat src = imread("1.jpg"); //工程目录下应该有一张名为1.jpg的素材图
Canny(src, src, 3, 9, 3);
imshow("【效果图】Canny边缘检测", src);
一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。
第三个参数,double类型的threshold1,第一个滞后性阈值。
第四个参数,double类型的threshold2,第二个滞后性阈值。
第五个参数,int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3。
第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。
需要注意的是,这个函数阈值1和阈值2两者的小者用于边缘连接,而大者用来控制强边缘的初始段,推荐的高低阈值比在2:1到3:1之间。
利用Sobel算子,sobel 产生的边缘有强弱,抗噪性好
C++: void Sobel (
InputArray src,//输入图
OutputArray dst,//输出图
int ddepth,//输出图像的深度
int dx,
int dy,
int ksize=3,
double scale=1,
double delta=0,
int borderType=BORDER_DEFAULT );
例子:
//【3】求 X方向梯度
Sobel( src, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x );
imshow("【效果图】 X方向Sobel", abs_grad_x);
//【4】求Y方向梯度
Sobel( src, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y );
imshow("【效果图】Y方向Sobel", abs_grad_y);
//【5】合并梯度(近似)
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst );
imshow("【效果图】整体方向Sobel", dst);
第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
若src.depth() = CV_64F, 取ddepth = -1/CV_64F
第四个参数,int类型dx,x 方向上的差分阶数。
第五个参数,int类型dy,y方向上的差分阶数。
第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
一般情况下,都是用ksize x ksize内核来计算导数的。然而,有一种特殊情况——当ksize为1时,往往会使用3 x 1或者1 x 3的内核。且这种情况下,并没有进行高斯平滑操作。
对边缘敏感,可能有些是噪声的边缘,也被算进来了
C++: void Laplacian(InputArray src,OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, intborderType=BORDER_DEFAULT );
例子:
Laplacian( src_gray, dst, CV_16S, 3, 1, 0, BORDER_DEFAULT );
第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和通道数。
第三个参数,int类型的ddept,目标图像的深度。
第四个参数,int类型的ksize,用于计算二阶导数的滤波器的孔径尺寸,大小必须为正奇数,且有默认值1。
第五个参数,double类型的scale,计算拉普拉斯值的时候可选的比例因子,有默认值1。
第六个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
第七个参数, int类型的borderType,边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate()处得到更详细的信息。
使用Scharr滤波器运算符计算x或y方向的图像差分。其实它的参数变量和Sobel基本上是一样的,除了没有ksize核的大小。
C++: void Scharr(
InputArray src, //源图
OutputArray dst, //目标图
int ddepth,//图像深度
int dx,// x方向上的差分阶数
int dy,//y方向上的差分阶数
double scale=1,//缩放因子
double delta=0,// delta值
intborderType=BORDER_DEFAULT )// 边界模式
例子:
第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
若src.depth() = CV_64F, 取ddepth = -1/CV_64F
第四个参数,int类型dx,x方向上的差分阶数。
第五个参数,int类型dy,y方向上的差分阶数。
第六个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
第七个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
第八个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
cornerHarris 函数用于在OpenCV中运行Harris角点检测算子处理图像。和cornerMinEigenVal( )以及cornerEigenValsAndVecs( )函数类似,cornerHarris 函数对于每一个像素(x,y)在blockSize x blockSize邻域内,计算2x2梯度的协方差矩阵 M(x,y),接着它计算如下式子:
dst(x,y) = detM(x,y) - k · (trM (x,y) )2
即可以找出输出图中的局部最大值,即找出了角点。
C++: void cornerHarris(InputArray src,
OutputArray dst,
int blockSize,
int ksize,
double k,
intborderType=BORDER_DEFAULT )
例子:
//进行角点检测
cornerHarris( g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT );
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸和类型。
第三个参数,int类型的blockSize,表示邻域的大小,更多的详细信息在cornerEigenValsAndVecs()中有讲到。
第四个参数,int类型的ksize,表示Sobel()算子的孔径大小。
第五个参数,double类型的k,Harris参数。
第六个参数,int类型的borderType,图像像素的边界模式,注意它有默认值BORDER_DEFAULT。更详细的解释,参考borderInterpolate( )函数。
void findContours( InputArray image,
OutputArrayOfArrays contours,
OutputArray hierarchy,
int mode,
int method,
Point offset = Point());
例子:
Mat image;
//image经过灰度化和二值化处理
vector<vector<Point>> contours; //二值图像轮廓的容器
vector<Vec4i> hierarchy; //4个int向量,分别表示后、前、父、子的索引编号
findContours(image, contours, hierarchy,RETR_LIST, CHAIN_APPROX_NONE); //检测所有轮廓
第一个参数:image,单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边 缘检测算子处理过的二值图像;
第二个参数:contours,定义为“vector
第三个参数:hierarchy,定义为“vector hierarchy”,先来看一下Vec4i的定义:
typedef Vec Vec4i;
Vec4i是Vec
所以从定义上看,hierarchy也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。
向量hiararchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。
hierarchy向量内每一个元素的4个int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表示第 i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。
如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~hierarchy[i][3]的相应位被设置为默认值-1。
此参数可不写,存在重载
第四个参数:int型的mode,定义轮廓的检索模式:
取值一:CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
取值二:CV_RETR_LIST 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关
系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,
所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到
取值三:CV_RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围
内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层
取值四:CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内
层轮廓还可以继续包含内嵌轮廓。
第五个参数:int型的method,定义轮廓的近似方法:
取值一:CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内
取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours
向量内,拐点与拐点之间直线段上的信息点不予保留
取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似
算法
第六个参数:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!
C++: void resize(InputArray src,
OutputArray dst,
Size dsize,
double fx=0,
double fy=0,
int interpolation=INTER_LINEAR )
例子:
简单的
cv::resize(image, image2, image.size());
复杂的
cv::resize(image, imageDilate, Size(image.cols * 2, image.rows * 2), (0.0), (0.0), INTER_LINEAR);
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
第二个参数,OutputArray类型的dst,输出图像,当其非零时,有着dsize(第三个参数)的尺寸,或者由src.size()计算出来。
第三个参数,Size类型的dsize,输出图像的大小;如果它等于零,由下式进行计算:
dsize = Size(round(fx*src.cols),round(fy*src.rows))
其中,dsize,fx,fy都不能为0。
第四个参数,double类型的fx,沿水平轴的缩放系数,有默认值0,且当其等于0时,由下式进行计算:
(double)dsize.width/src.cols
第五个参数,double类型的fy,沿垂直轴的缩放系数,有默认值0,且当其等于0时,由下式进行计算:
(double)dsize.height/src.rows
第六个参数,int类型的interpolation,用于指定插值方式,默认为INTER_LINEAR(线性插值)。
可选的插值方式如下:
INTER_NEAREST - 最近邻插值
INTER_LINEAR - 线性插值(默认值)
INTER_AREA - 区域插值(利用像素区域关系的重采样插值)
INTER_CUBIC –三次样条插值(超过4×4像素邻域内的双三次插值)
INTER_LANCZOS4 -Lanczos插值(超过8×8像素邻域的Lanczos插值)
若要缩小图像,一般情况下最好用INTER_AREA来插值,
而若要放大图像,一般情况下最好用INTER_CUBIC(效率不高,慢,不推荐使用)或INTER_LINEAR(效率较高,速度较快,推荐使用)。
pyrUp( )函数的作用是向上采样并模糊一张图像,说白了就是放大一张图片。
C++: void pyrUp(InputArray src, OutputArraydst, const Size& dstsize=Size(), int borderType=BORDER_DEFAULT )
例子:
pyrUp( g_tmpImage, g_dstImage, Size( g_tmpImage.cols*2, g_tmpImage.rows*2 ));
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
第二个参数,OutputArray类型的dst,输出图像,和源图片有一样的尺寸和类型。
第三个参数,const Size&类型的dstsize,输出图像的大小;有默认值Size(),即默认情况下,由Size(src.cols2,src.rows2)来进行计算,且一直需要满足下列条件:
|dstsize.width - src.cols * 2| ≤ (dstsize.width mod 2)
|dstsize.height - src.rows * 2| ≤ (dstsize.height mod 2)
第四个参数,int类型的borderType,又来了,边界模式,一般我们不用去管它。
pyrUp函数执行高斯金字塔的采样操作,其实它也可以用于拉普拉斯金字塔的。
首先,它通过插入可为零的行与列,对源图像进行向上取样操作,然后将结果与pyrDown()乘以4的内核做卷积,就是这样。
pyrDown( )函数的作用是向下采样并模糊一张图片,说白了就是缩小一张图片。
C++: void pyrDown(InputArray src,OutputArray dst, const Size& dstsize=Size(), int borderType=BORDER_DEFAULT)
例子:
pyrDown( tmpImage, dstImage, Size( tmpImage.cols/2, tmpImage.rows/2 ) );
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
第二个参数,OutputArray类型的dst,输出图像,和源图片有一样的尺寸和类型。
第三个参数,const Size&类型的dstsize,输出图像的大小;有默认值Size(),即默认情况下,由Size Size((src.cols+1)/2, (src.rows+1)/2)来进行计算,且一直需要满足下列条件:
|dstsize.width * 2 - src.cols| ≤ 2
|dstsize.height * 2 - src.rows| ≤ 2
该pyrDown函数执行了高斯金字塔建造的向下采样的步骤。首先,它将源图像与如下内核做卷积运算:
接着,它便通过对图像的偶数行和列做插值来进行向下采样操作。
void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
例子:
line(dstImage, Point(100, 100), Point(200, 200), Scalar(55, 100, 195), 1, CV_AA);
#include -->CV_AA头文件
img: 要绘制线段的图像。
pt1: 线段的起点。
pt2: 线段的终点。
color: 线段的颜色,通过一个Scalar对象定义。
thickness: 线条的宽度。
lineType: 线段的类型。可以取值8, 4, 和CV_AA(16), 分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用CV_AA(采用了高斯滤波)。
shift: 坐标点小数点位数
void rectangle(InputOutputArray img, Point pt1, Point pt2,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
void rectangle(InputOutputArray img,
Rect rec,
const Scalar& color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0);
例子:
rectangle( dstImage, Point(384, 0), Point(510, 128), Scalar(0, 255, 0), 3);
img,要绘制线段的图像。
pt1,矩形左上角的Point点
pt2,矩形右下角的Point点
rec,矩形范围
color,线段的颜色,通过一个Scalar对象定义。
thickness,线段的宽度,如果为-1则是填充
lineType,线段的类型。可以取值8, 4, 和CV_AA(16), 分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用CV_AA(采用了高斯滤波)。
shift,坐标点小数点位数
void circle(InputOutputArray img,
Point center,
int radius,
const Scalar& color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0);
例子:
//绘制圆心
circle( srcImage, center, 3, Scalar(0,255,0), -1, 8, 0 );
//绘制圆轮廓
circle( srcImage, center, radius, Scalar(155,50,255), 3, 8, 0 );
img为源图像指针
center为画圆的圆心坐标
radius为圆的半径
color为设定圆的颜色,规则根据B(蓝)G(绿)R(红)
thickness 如果是正数,表示组成圆的线条的粗细程度。否则,-1表示圆是否被填充
line_type 线段的类型。可以取值8, 4, 和CV_AA(16), 分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用CV_AA(采用了高斯滤波)。
shift 圆心坐标点和半径值的小数点位数
void ellipse(InputOutputArray img, Point center, Size axes,
double angle, double startAngle, double endAngle,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
void ellipse(InputOutputArray img, const RotatedRect& box, const Scalar& color,
int thickness = 1, int lineType = LINE_8);
例子:
ellipse( srcImage, Point(256, 256), Size(100, 50), 0, 0, 360, 255, -1);
img,要绘制的图像
center,椭圆中心点
axes,椭圆主轴尺寸的一半。
angle,整个椭圆的角度
startAngle,开始角度,以x轴方向为0,顺时针方向递增
endAngle,绘制结束角度
box,通过RotatedRect可选椭圆表示。这意味着该函数在旋转后的矩形内画一个椭圆。
color,椭圆颜色
thickness,线段的宽度,-1为填充
lineType,线段的类型。可以取值8, 4, 和CV_AA(16), 分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用CV_AA(采用了高斯滤波)。
shift,参数数值的小数点位数
此函数可以找出采用标准霍夫变换的二值图像线条。在OpenCV中,我们可以用其来调用标准霍夫变换SHT和多尺度霍夫变换MSHT的OpenCV内建算法。
void cv::HoughLines (InputArray image, //8位,单通道二值源图像。该函数可以修改图像。
OutputArray lines,//输出直线vector(ρ,θ) or (ρ,θ,votes)
//ρ是距坐标原点的距离,
//θ是以弧度表示的线旋转角度(0∼垂直直线,π/2∼水平直线)
//votes 曲线交点累加计数
double rho, //以像素为单位的累加器的距离分辨率。 推荐用1.0;
double theta, //以弧度表示的累加器角度分辨率。 CV_PI/180
int threshold, //累加计数大于此阈值才返回 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。根据情况推荐先用100试试;
double srn = 0,
double stn = 0,
double min_theta = 0, //检查线条的最小角度。必须介于0和maxθ之间。
double max_theta = CV_PI //要检查线条的最大角度。必须介于minθ和CV_PI之间。
)
例子:
vector<Vec2f> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合
HoughLines(midImage, lines, 1, CV_PI/180, 150, 0, 0 );
第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。
第二个参数,OutputArray类型的lines,经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量表示,其中,是离坐标原点((0,0)(也就是图像的左上角)的距离。 是弧度线条旋转角度(0垂直线,π/2水平线)。
第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。PS:Latex中/rho就表示 。
第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
第六个参数,double类型的srn,有默认值0。对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离。粗略的累加器进步尺寸直接是第三个参数rho,而精确的累加器进步尺寸为rho/srn。
第七个参数,double类型的stn,有默认值0,对于多尺度霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离。且如果srn和stn同时为0,就表示使用经典的霍夫变换。否则,这两个参数应该都为正数。
第八个参数,double类型的 min_theta,对于标准和多尺度Hough变换,检查线条的最小角度。必须介于0和max_theta之间。
第九个参数,double类型的 max_theta, 对于标准和多尺度Hough变换,检查线条的最大角度。必须介于min_theta和CV_PI之间.
此函数在HoughLines的基础上末尾加了一个代表Probabilistic(概率)的P,表明它可以采用累计概率霍夫变换(PPHT)来找出二值图像中的直线。
C++: void HoughLinesP(InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength=0,
double maxLineGap=0 )
例子:
vector<Vec2f> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合
HoughLinesP(can_img, lines, 1., CV_PI / 180, 200, 100, 2);
第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。
第二个参数,OutputArray类型的lines,经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的结束点。
第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。
第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
第六个参数,double类型的minLineLength,有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。
第七个参数,double类型的maxLineGap,有默认值0,允许将同一行点与点之间连接起来的最大的距离。
倒数三个参数不了解可以看看学不会的程序员
HoughCircles函数可以利用霍夫变换算法检测出灰度图中的圆。它和之前的HoughLines和HoughLinesP比较明显的一个区别是它不需要源图是二值的,而HoughLines和HoughLinesP都需要源图为二值图像。
C++: void HoughCircles(InputArray image,
OutputArray circles,
int method,
double dp,
double minDist,
double param1=100,
double param2=100,
int minRadius=0,
int maxRadius=0 )
例子:
vector<Vec3f> circles;
HoughCircles( midImage, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100, 0, 0 );
第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的灰度单通道图像。
第二个参数,OutputArray类型的circles,经过调用HoughCircles函数后此参数存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x, y, radius)表示。
第三个参数,int类型的method,即使用的检测方法,目前OpenCV中就霍夫梯度法一种可以使用,它的标识符为CV_HOUGH_GRADIENT,在此参数处填这个标识符即可。
第四个参数,double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度。
第五个参数,double类型的minDist,为霍夫变换检测到的圆的圆心之间的最小距离,即让我们的算法能明显区分的两个不同圆之间的最小距离。这个参数如果太小的话,多个相邻的圆可能被错误地检测成了一个重合的圆。反之,这个参数设置太大的话,某些圆就不能被检测出来了。
第六个参数,double类型的param1,有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
第七个参数,double类型的param2,也有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
第八个参数,int类型的minRadius,有默认值0,表示圆半径的最小值。
第九个参数,int类型的maxRadius,也有默认值0,表示圆半径的最大值。
需要注意的是,使用此函数可以很容易地检测出圆的圆心,但是它可能找不到合适的圆半径。我们可以通过第八个参数minRadius和第九个参数maxRadius指定最小和最大的圆半径,来辅助圆检测的效果。或者,我们可以直接忽略返回半径,因为它们都有着默认值0,单单用HoughCircles函数检测出来的圆心,然后用额外的一些步骤来进一步确定半径。
就是画图的那种填充功能,无从下手传送门
//7个参数
int floodFill(InputOutputArray image,
Point seedPoint,
Scalar newVal,
Rect* rect=0,
Scalar loDiff=Scalar(),
Scalar upDiff=Scalar(),
int flags=4 )
//8个参数,多了第二个
int floodFill(InputOutputArray image,
InputOutputArray mask,
Point seedPoint,
Scalar newVal,
Rect* rect=0,
Scalar loDiff=Scalar(),
Scalar upDiff=Scalar(),
int flags=4 )
例子:
Rect ccomp;
floodFill(image, Point(50,300), Scalar(155, 255,55), &ccomp, Scalar(20, 20, 20),Scalar(20, 20, 20));
第一个参数,InputOutputArray类型的image, 输入/输出1通道或3通道,8位或浮点图像,具体参数由之后的参数具体指明。
第二个参数, InputOutputArray类型的mask,这是第二个版本的floodFill独享的参数,表示操作掩模,它应该为单通道、8位、长和宽上都比输入图像 image 大两个像素点的图像。第二个版本的floodFill需要使用以及更新掩膜,所以这个mask参数我们一定要将其准备好并填在此处。需要注意的是,漫水填充不会填充掩膜mask的非零像素区域。例如,一个边缘检测算子的输出可以用来作为掩膜,以防止填充到边缘。同样的,也可以在多次的函数调用中使用同一个掩膜,以保证填充的区域不会重叠。另外需要注意的是,掩膜mask会比需填充的图像大,所以 mask 中与输入图像(x,y)像素点相对应的点的坐标为(x+1,y+1)。
第三个参数,Point类型的seedPoint,漫水填充算法的起始点。
第四个参数,Scalar类型的newVal,像素点被染色的值,即在重绘区域像素的新值。
第五个参数,Rect*类型的rect,有默认值0,一个可选的参数,用于设置floodFill函数将要重绘区域的最小边界矩形区域。
第六个参数,Scalar类型的loDiff,有默认值Scalar( ),表示当前观察像素值与其部件邻域像素值或者待加入该部件的种子像素之间的亮度或颜色之负差(lower brightness/color difference)的最大值。
第七个参数,Scalar类型的upDiff,有默认值Scalar( ),表示当前观察像素值与其部件邻域像素值或者待加入该部件的种子像素之间的亮度或颜色之正差(lower brightness/color difference)的最大值。
第八个参数,int类型的flags,操作标志符,此参数包含三个部分,比较复杂,我们一起详细看看。
低八位(第0~7位)用于控制算法的连通性,可取4 (4为缺省值) 或者 8。如果设为4,表示填充算法只考虑当前像素水平方向和垂直方向的相邻点;如果设为 8,除上述相邻点外,还会包含对角线方向的相邻点。
高八位部分(16~23位)可以为0 或者如下两种选项标识符的组合:
enum FloodFillFlags {
/** If set, the difference between the current pixel and seed pixel is considered. Otherwise,
the difference between neighbor pixels is considered (that is, the range is floating). */
FLOODFILL_FIXED_RANGE = 1 << 16,
/** If set, the function does not change the image ( newVal is ignored), and only fills the
mask with the value specified in bits 8-16 of flags as described above. This option only make
sense in function variants that have the mask parameter. */
FLOODFILL_MASK_ONLY = 1 << 17
};
FLOODFILL_FIXED_RANGE - 如果设置为这个标识符的话,就会考虑当前像素与种子像素之间的差,否则就考虑当前像素与其相邻像素的差。也就是说,这个范围是浮动的。
FLOODFILL_MASK_ONLY - 如果设置为这个标识符的话,函数不会去填充改变原始图像 (也就是忽略第三个参数newVal), 而是去填充掩模图像(mask)。这个标识符只对第二个版本的floodFill有用,因第一个版本里面压根就没有mask参数。
中间八位部分(第8~15位),上面关于高八位FLOODFILL_MASK_ONLY标识符中已经说的很明显,需要输入符合要求的掩码。Floodfill的flags参数的中间八位的值就是用于指定填充掩码图像的值的。但如果flags中间八位的值为0,则掩码会用1来填充。
C++: void drawKeypoints(const Mat&image,
const vector<KeyPoint>& keypoints,
Mat& outImage,
constScalar& color=Scalar::all(-1),
int flags=DrawMatchesFlags::DEFAULT )
例子:
std::vector<KeyPoint> keypoints_1;//vector模板类是能够存放任意类型的动态数组,能够增加和压缩数据
//【3】调用detect函数检测出SURF特征关键点,保存在vector容器中
detector.detect( srcImage1, keypoints_1 );
//【4】绘制特征关键点
Mat img_keypoints_1;
drawKeypoints( srcImage1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
第一个参数,const Mat&类型的src,输入图像。
第二个参数,const vector< KeyPoint>&类型的keypoints,根据源图像得到的特征点,它是一个输出参数。
第三个参数,Mat&类型的outImage,输出图像,其内容取决于第五个参数标识符falgs。
第四个参数,const Scalar&类型的color,关键点的颜色,有默认值Scalar::all(-1)。
第五个参数,int类型的flags,绘制关键点的特征标识符,有默认值DrawMatchesFlags::DEFAULT。可以在如下这个结构体中选取值。
struct DrawMatchesFlags
{
enum
{
DEFAULT = 0, // Output image matrix will be created (Mat::create),
// i.e. existing memory of output image may be reused.
// Two source images, matches, and single keypoints
// will be drawn.
// For each keypoint, only the center point will be
// drawn (without a circle around the keypoint with the
// keypoint size and orientation).
DRAW_OVER_OUTIMG = 1, // Output image matrix will not be
// created (using Mat::create). Matches will be drawn
// on existing content of output image.
NOT_DRAW_SINGLE_POINTS = 2, // Single keypoints will not be drawn.
DRAW_RICH_KEYPOINTS = 4 // For each keypoint, the circle around
// keypoint with keypoint size and orientation will
// be drawn.
};
};
drawMatches用于绘制出相匹配的两个图像的关键点,它有如下两个版本的C++函数原型:
C++: void drawMatches(const Mat& img1,
constvector<KeyPoint>& keypoints1,
const Mat& img2,
constvector<KeyPoint>& keypoints2,
constvector<DMatch>& matches1to2,
Mat& outImg,
const Scalar&matchColor=Scalar::all(-1),
const Scalar&singlePointColor=Scalar::all(-1),
const vector<char>&matchesMask=vector<char>(),
intflags=DrawMatchesFlags::DEFAULT )
C++: void drawMatches(const Mat& img1,
constvector<KeyPoint>& keypoints1,
const Mat& img2,
constvector<KeyPoint>& keypoints2,
const vector<vector<DMatch>>&matches1to2,
Mat& outImg,
const Scalar&matchColor=Scalar::all(-1),
const Scalar&singlePointColor=Scalar::all(-1),
constvector<vector<char>>& matchesMask=vector<vector<char>>(),
intflags=DrawMatchesFlags::DEFAULT )
例子:
//【1】载入素材图
Mat srcImage1 = imread("1.jpg",1);
Mat srcImage2 = imread("2.jpg",1);
if( !srcImage1.data || !srcImage2.data )
{ printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }
//【2】使用SURF算子检测关键点
int minHessian = 700;//SURF算法中的hessian阈值
SurfFeatureDetector detector( minHessian );//定义一个SurfFeatureDetector(SURF) 特征检测类对象
std::vector<KeyPoint> keyPoint1, keyPoints2;//vector模板类,存放任意类型的动态数组
//【3】调用detect函数检测出SURF特征关键点,保存在vector容器中
detector.detect( srcImage1, keyPoint1 );
detector.detect( srcImage2, keyPoints2 );
//【4】计算描述符(特征向量)
SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute( srcImage1, keyPoint1, descriptors1 );
extractor.compute( srcImage2, keyPoints2, descriptors2 );
//【5】使用BruteForce进行匹配
// 实例化一个匹配器
BruteForceMatcher< L2<float> > matcher;
std::vector< DMatch > matches;
//匹配两幅图中的描述子(descriptors)
matcher.match( descriptors1, descriptors2, matches );
//【6】绘制从两个图像中匹配出的关键点
Mat imgMatches;
drawMatches( srcImage1, keyPoint1, srcImage2, keyPoints2, matches, imgMatches );//进行绘制
除了第五个参数matches1to2和第九个参数matchesMask有细微的差别以外,两个版本的基本上相同。
第一个参数,const Mat&类型的img1,第一幅源图像。
第二个参数,const vector&类型的keypoints1,根据第一幅源图像得到的特征点,它是一个输出参数。
第三个参数,const Mat&类型的img2,第二幅源图像。
第四个参数,const vector&类型的keypoints2,根据第二幅源图像得到的特征点,它是一个输出参数。
第五个参数,matches1to2,第一幅图像到第二幅图像的匹配点,即表示每一个图1中的特征点都在图2中有一一对应的点、
第六个参数,Mat&类型的outImg,输出图像,其内容取决于第五个参数标识符falgs。
第七个参数,const Scalar&类型的matchColor,匹配的输出颜色,即线和关键点的颜色。它有默认值Scalar::all(-1),表示颜色是随机生成的。
第八个参数,const Scalar&类型的singlePointColor,单一特征点的颜色,它也有表示随机生成颜色的默认值Scalar::all(-1)。
第九个参数,matchesMask,确定哪些匹配是会绘制出来的掩膜,如果掩膜为空,表示所有匹配都进行绘制。
第十个参数,int类型的flags,特征绘制的标识符,有默认值DrawMatchesFlags::DEFAULT。可以在如下这个DrawMatchesFlags结构体中选取值:
struct DrawMatchesFlags
{
enum
{
DEFAULT = 0, // Output image matrix will be created (Mat::create),
// i.e. existing memory ofoutput image may be reused.
// Two source images,matches, and single keypoints
// will be drawn.
// For each keypoint, only the center pointwill be
// drawn (without a circlearound the keypoint with the
// keypoint size andorientation).
DRAW_OVER_OUTIMG = 1, // Output image matrix will not be
// created (usingMat::create). Matches will be drawn
// on existing contentof output image.
NOT_DRAW_SINGLE_POINTS = 2, // Single keypoints will not be drawn.
DRAW_RICH_KEYPOINTS = 4 // For each keypoint, the circle around
// keypoint withkeypoint size and orientation will
// be drawn.
};
};
void drawContours( InputOutputArray image,
InputArrayOfArrays contours,
int contourIdx,
const Scalar& color,
int thickness = 1,
int lineType = LINE_8,
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX,
Point offset = Point() );
例子:
//pDst是取contours轮廓值时用的二值化图像的,同等长宽但zero过的Mat图像
//contours[i]代表第i个轮廓,contours[i].size()代表第i个轮廓上所有的像素点
for (int i = 0; i < contours.size(); i++)
{
for (int j = 0; j < contours[i].size(); j++)
{
//获取轮廓上点的坐标
Point P = Point(contours[i][j].x, contours[i][j].y);
}
drawContours(pDst, contours,i, Scalar(255), -1, 8);
}
第一个参数,image目标图像。
第二个参数,contours所有的输入轮廓。每条轮廓线存储为一个点向量。
第三个参数,contourIdx要绘制的轮廓参数。如果它是负的,就画出所有的等高线。
第四个参数,color轮廓的颜色。
第五个参数,厚度绘制轮廓线的线的厚度。如果它是负的(例如,厚度=#FILLED),绘制轮廓内部。
第六个参数,lineType线路连接。看到#线型
类型 含义
8 8 连通线型
4 4 连通线型
LINE_AA 抗锯齿线型
第七个参数,hierarchy可选信息。它只在你想画画时才需要一些轮廓(参见maxLevel)。
第八个参数,maxLevel绘制轮廓的最大等级。如果为0,则只绘制指定的轮廓。
如果为1,函数绘制轮廓线和所有嵌套轮廓线。如果是2,函数
绘制等高线、所有嵌套等高线、所有嵌套到嵌套等高线等等。这
参数只在存在可用层次结构时被考虑。
第九个参数,offset可选轮廓偏移参数。按指定的方式移动所有绘制的轮廓
\ f $ \ texttt{抵消}= (dx, dy) \ f $。
.
explicit VideoCapture(const String& filename, int apiPreference = CAP_ANY);
explicit VideoCapture(int index, int apiPreference = CAP_ANY);
virtual void release(); //关闭摄像头
例子:
VideoCapture cap = VideoCapture( "test.avi" );
VideoCapture cap = VideoCapture( 0 );
cap.release();
第一条可打开一个视频文件或捕获设备或IP视频流的视频捕获与API首选项;
第二条利用VideoCapture
的构造函数打开摄像头列表的index项。
filename,打开的视频文件名
文件名可以是:
-视频文件的名称(例如。“video.avi”)
-或图像序列(如。' img_%02d.jpg ',读取的样本为' img_00.jpg, img_01.jpg, img_02.jpg,…')
-或视频流的URL。协议:/ /主持人:港口/ script_name ? script_params |认证”)
如果使用GStreamer作为后端,则使用gst-launch工具格式的GStreamer管道字符串
index,要打开的视频捕捉设备的索引id。使用默认后端打开默认摄像头,只需通过0。
(当apiPreference为CAP_ANY时,camera_id + domain_offset (CAP_*)的向后兼容使用有效)。
apiPreference,apiPreference优先使用的捕获API后端。能否用于强制特定的读取器。
virtual bool read(OutputArray image);
例子:
Mat frame;
bool ret = cap.read( frame );
从摄像头实时读取一帧
image,读取到的帧将会放到image里,一般是Mat类型的。
返回值,返回读取成功与否。
virtual double get(int propId) const;
例子:
cout << cap.get( CAP_PROP_FRAME_WIDTH) << cap.get( CAP_PROP_FRAME_HEIGHT );
propId,设好的VideoCaptureProperties枚举,根据对应枚举可返回对应数据。
返回值,返回指定属性的值,如例子是分别返回宽和高。当查询videcapture实例使用的后端不支持的属性时,返回0。
提醒:返回值可能与设备实际使用的值不同,或者可以使用设备相关的规则对其进行编码(步骤或百分比)。有效的行为取决于设备驱动程序和API后端。
virtual bool set(int propId, double value);
例子:
cap.set( CAP_PROP_FRAME_WIDTH, 320 );
propId,同上,propId属性标识符来自cv::VideoCaptureProperties或者来自@ref videoio_flags_others。
value,要修改对应的属性值。
返回值,返回修改成功与否。
.
注:我后续学会了新的函数也会继续记录在此,没有特别写明的变量基本都是Mat类型的