Mat a(Size(2560,1440),CV_8UC3);
for(auto iter=a.begin<Vec3b>();iter!=a.end<Vec3b>();iter++){
iter[0]=255;
iter[1]=0;
iter[2]=0;
}
3.图像基本操作
3.1 图片读取
CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR );
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.
};
3.2 创建窗口
CV_EXPORTS_W void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
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
};
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai", xuenai);
Mat xuenai_rotate(xuenai.size(), xuenai.type());
rotate(xuenai, xuenai_rotate, ROTATE_180);
imshow("xuenai_rotate", xuenai_rotate);
waitKet();
3.15 仿射变换
3.15.1 API
CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
参数如下
参数
含义
src(source)
输入图片
dst(destination)
输出图片
M
变换矩阵
dsize(destination size)
输出图片的尺寸,若不对输出图片的尺寸进行调整,那么很可能会出现黑边
flags
插值算法
borderMode
边界外推法
borderValue
填充边界的值
3.15.2 平移
只需将变换矩阵M设置成如下形式:
float delta_x=200,delta_y=200;
float M_values[]={1,0,delta_x,
0,1,delta_y};
Mat M(Size(3,2),CV_32F,M_values);
delta_x:x方向上的偏移量
delta_y:y方向上的偏移量
M_values:必须是浮点类型的数组对象
M:必须是CV_32F,不能用逗号式分隔创建
效果
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
double M_values[]={1,0,200,
0,1,200};
Mat M(Size(3,2), CV_64F,M_values);
Mat xuenai_shift(xuenai.size(),xuenai.type());
warpAffine(xuenai,xuenai_shift,M,xuenai.size());
imshow("xuenai_shift",xuenai_shift);
waitKet();
3.15.3 任意角度旋转
获得变换矩阵M
inline
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
{
return Mat(getRotationMatrix2D_(center, angle, scale), true);
}
参数如下
参数
含义
center
旋转中心点的坐标
angle
逆时针偏角
scale
生成图与原图之比
效果
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai", xuenai);
Mat M= getRotationMatrix2D(Point2f(xuenai.cols/2,xuenai.rows/2),45,1);
Mat xuenai_rotate(xuenai.size(),xuenai.type());
warpAffine(xuenai,xuenai_rotate,M,xuenai.size());
imshow("xuenai_flip",xuenai_rotate);
3.15.4 仿射(不破坏几何关系)
获得变换矩阵M
CV_EXPORTS Mat getAffineTransform( const Point2f src[], const Point2f dst[] );
参数如下
参数
含义
src[](source[])
输入图片的坐标点集,含三个坐标点
dst[](destination[])
三个坐标点变换的目标位置
三个点要一一对应
3.16 透射变换(破坏几何关系)
3.16.1 API
进行变换
CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
参数如下
参数
含义
src(source)
输入图片
dst(destination)
输出图片
M
变换矩阵
dsize(destination size)
输出图片的尺寸,若不对输出图片的尺寸进行调整,那么很可能会出现黑边
flags
插值算法
borderMode
边界外推法
borderValue
填充边界的值
已知变换后图片,逆推变换矩阵M
CV_EXPORTS_W Mat getPerspectiveTransform(InputArray src, InputArray dst, int solveMethod = DECOMP_LU);
参数如下
参数
含义
src(source)
输入图片
dst(destination)
输出图片
获得变换矩阵M
CV_EXPORTS Mat getPerspectiveTransform(const Point2f src[], const Point2f dst[], int solveMethod = DECOMP_LU);
参数如下
参数
含义
src[](source[])
输入图片的坐标点集,含四个坐标点
dst[](destination[])
三个坐标点变换的目标位置
四个点要一一对应
3.16.2 效果
Mat origin = imread("origin.jpg");
Point2f point2F_origin[4]={Point2f (405,105),Point2f(2469,217),Point2f(2573,3489),Point2f(349,3547)};
Point2f point2F_tansform[4]={Point2f (0,0),Point2f(2500,0),Point2f(2500,3500),Point2f(0,3500)};
Mat M=getPerspectiveTransform(point2F_origin,point2F_tansform);
Mat transfrom(origin.size(),origin.type());
warpPerspective(origin,transfrom,M,Size(2500,3500));
resize(origin,origin,Size(500,700));
resize(transfrom,transfrom,Size(500,700));
imshow("origin",origin);
imshow("transform",transfrom);
4.滤波及边缘检测
4.1 均值滤波
4.1.1 卷积核形状
Mat kernal=Mat::ones(Size(ksize,ksize),CV_64F)/(ksize*ksize);
4.1.2 API
CV_EXPORTS_W void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT );
参数如下
参数
含义
src(source)
输入图片
dst(destination)
输出图片
ksize(kernal size)
卷积核宽高,必须是正奇数
anchor
滤波器中心像素位置,取(-1,-1)表示几何中心
borderType
边界填充方式,默认为黑边
4.1.3 效果
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_blur(xuenai.size(),xuenai.type());
blur(xuenai,xuenai_blur,Size(3,5));
imshow("xuenai_blur",xuenai_blur);
waitKet();
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_Gauss(xuenai.size(),xuenai.type());
GaussianBlur(xuenai,xuenai_Gauss,Size(-1,-1),10);
imshow("xuenai_Gauss",xuenai_Gauss);
waitKet();
4.3 中值滤波
4.3.1 原理
取滤波器内的中值作为输出,可以很好的抑制椒盐噪声
4.3.2 API
CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
参数如下
参数
含义
src(source)
输入图片
dst(destination)
输出图片
ksize(kernal size)
卷积核边长,必须是正奇数
4.3.3 效果
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_median(xuenai.size(),xuenai.type());
medianBlur(xuenai,xuenai_median,5);
imshow("xuenai_median",xuenai_median);
waitKet();
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_bilateral(xuenai.size(),xuenai.type());
bilateralFilter(xuenai,xuenai_bilateral,-1,100,10);
imshow("xuenai_bilateral",xuenai_bilateral);
waitKet();
4.5 获取用来形态学操作的滤波器
CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
enum MorphShapes {
MORPH_RECT = 0, //!< a rectangular structuring element: \f[E_{ij}=1\f]
MORPH_CROSS = 1, //!< a cross-shaped structuring element:
//!< \f[E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}\f]
MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed
//!< into the rectangle Rect(0, 0, esize.width, 0.esize.height)
};
shape:滤波器形状
ksize(kernal size):滤波器大小
anchor:滤波器中心像素位置,取(-1,-1)表示几何中心
4.6 腐蚀和膨胀(对二值图)
4.6.1 原理
腐蚀:取滤波器内的最小值作为输出
膨胀:取滤波器内的最大值作为输出
4.6.2 腐蚀API
CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数如下
参数
含义
src(source)
输入图片,尽量是二值图
dst(destination)
输出图片
kernal
滤波器矩阵
anchor
滤波器中心像素位置,取(-1,-1)表示几何中心
iterations
执行erode函数的次数,默认执行一次
borderType
边界填充方式,默认为黑边
borderValue
填充边界的值
4.6.3 效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_erode(xuenai.size(),xuenai.type());
erode(xuenai_threshold,xuenai_erode,kernal);
imshow("xuenai_erode",xuenai_erode);
waitKet();
4.6.4 膨胀API
CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数如下
参数
含义
src(source)
输入图片,尽量是二值图
dst(destination)
输出图片
kernal
滤波器矩阵
anchor
滤波器中心像素位置,取(-1,-1)表示几何中心
iterations
执行erode函数的次数,默认执行一次
borderType
边界填充方式,默认为黑边
borderValue
填充边界的值
4.6.5 效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_dilate(xuenai.size(),xuenai.type());
dilate(xuenai_threshold,xuenai_dilate,kernal);
imshow("xuenai_dilate",xuenai_dilate);
waitKet();
4.7 形态学操作(对二值图)
4.7.1 API
CV_EXPORTS_W void morphologyEx( InputArray src, OutputArray dst,
int op, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_OPEN,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
4.7.4 闭
原理
对输入图片先进行膨胀,然后进行腐蚀。可以用来屏蔽与滤波器大小相当的暗部。
效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_CLOSE,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
4.7.5 顶帽
原理
对输入图片先进行开操作,然后原图-开操作图。可以用来提取与滤波器大小相当的亮部。
效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_TOPHAT,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
4.7.6 黑帽
原理
对输入图片先进行闭操作,然后闭操作图-原图。可以用来提取与滤波器大小相当的暗部。
效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_BLACKHAT,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
4.7.7 形态学梯度
原理
膨胀图与腐蚀图之差。可以用来 提取边界轮廓 ,但提取效果比不上专业的边缘检测算法。
效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_GRADIENT,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
enum NormTypes {
NORM_INF = 1,
NORM_L1 = 2,
NORM_L2 = 4,
NORM_L2SQR = 5,
NORM_HAMMING = 6,
NORM_HAMMING2 = 7,
NORM_TYPE_MASK = 7, //!< bit-mask which can be used to separate norm type from norm flags
NORM_RELATIVE = 8, //!< flag
NORM_MINMAX = 32 //!< flag
};
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_canny(xuenai.size(),xuenai.type());
Canny(xuenai,xuenai_canny,60,150);
imshow("xuenai_canny",xuenai_canny);
waitKet();
4.13 添加噪声
为了检测算法的稳定性,常常需要在图片中人为地添加一些噪声来进行检验。
4.13.1 椒盐噪声
static void addSaltNoise(const Mat& src,Mat& dst,int num=1000)
{
dst=src.clone();
for (int k = 0; k < num; k++)
{
//随机取值行列,得到像素点(i,j)
int i = rand() % dst.rows;
int j = rand() % dst.cols;
//修改像素点(i,j)的像素值
for(int channel=0;channel<src.channels();channel++){
dst.ptr(i,j)[channel]=255;
}
}
for (int k = 0; k < num; k++)
{
//随机取值行列
default_random_engine engine;
uniform_int_distribution<unsigned>u(0,10000);
int i = rand() % dst.rows;
int j = rand() % dst.cols;
//修改像素点(i,j)的像素值
for(int channel=0;channel<src.channels();channel++){
dst.ptr(i,j)[channel]=0;
}
}
return;
}
CV_EXPORTS_W void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,int thickness = 1, int lineType = LINE_8, int shift = 0);
参数如下
参数
含义
img(image)
绘制多边形的画布,数据类型Mat
pt1(point1)
端点1
pt2(point2)
端点2
color
绘制线条的颜色
thickness
绘制线条的粗细
lineType
绘制线条的连通类型
shift
坐标点小数点位数(not important)
5.1.2 连通类型
enum LineTypes {
FILLED = -1,
LINE_4 = 4, //!< 4-connected line
LINE_8 = 8, //!< 8-connected line
LINE_AA = 16 //!< antialiased line
};
LINE_4与LINE_8差别不大,而LINE_AA的抗锯齿效果显著
5.2 正矩形
5.2.1API
CV_EXPORTS_W void rectangle(InputOutputArray img, Point pt1, Point pt2,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
参数如下
参数
含义
img(image)
绘制多边形的画布,数据类型Mat
pt1(point1)
左上角端点
pt2(point2)
右下角端点
color
绘制线条的颜色
thickness
绘制线条的粗细。若取负值,则表示进行填充
lineType
绘制线条的连通类型
shift
坐标点小数点位数(not important)
CV_EXPORTS_W void rectangle(InputOutputArray img, Rect rec,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
参数如下
参数
含义
img(image)
绘制多边形的画布,数据类型Mat
rec(rect)
一个矩形
color
绘制线条的颜色
thickness
绘制线条的粗细。若取负值,则表示进行填充
lineType
绘制线条的连通类型
shift
坐标点小数点位数(not important)
5.3 圆形
5.3.1 API
CV_EXPORTS_W void circle(InputOutputArray img, Point center, int radius,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
参数如下
参数
含义
img(image)
绘制多边形的画布,数据类型Mat
center
圆心坐标
radius
半径
color
绘制线条的颜色
thickness
绘制线条的粗细。若取负值,则表示进行填充
lineType
绘制线条的连通类型
shift
坐标点小数点位数(not important)
5.4 椭圆
5.4.1 API
CV_EXPORTS_W 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);
参数如下
参数
含义
img(image)
绘制多边形的画布,数据类型Mat
center
圆心坐标
axes
(x方向上半轴长,y方向上半轴长)
angle
顺时针偏角
startAngle
以x方向上的正半轴为起点,偏移一定角度后的起点,从此起点开始画椭圆
endAngle
以x方向上的正半轴为起点,偏移一定角度后的终点,到此为止结束画椭圆
color
绘制线条的颜色
thickness
绘制线条的粗细。若取负值,则表示进行填充
lineType
绘制线条的连通类型
shift
坐标点小数点位数(not important)
5.4.2 效果
Mat canvas(Size(1000,1000),CV_8U,Scalar(255));
ellipse(canvas,Point2f(500,500),Size(50,100),0,0,90,Scalar(0,0,0),5);
imshow("canvas",canvas);
waitKey();
Mat canvas(Size(1000,1000),CV_8U,Scalar(255));
ellipse(canvas,Point2f(500,500),Size(50,100),20,0,360,Scalar(0,0,0),5);
imshow("canvas",canvas);
waitKey();
Mat canvas(Size(1000,1000),CV_8U,Scalar(255));
ellipse(canvas,Point2f(500,500),Size(50,100),20,0,180,Scalar(0,0,0),5);
imshow("canvas",canvas);
waitKey();
5.5 斜矩形
5.5.1 API(通过RotatedRect类和line函数实现)
class CV_EXPORTS RotatedRect
{
public:
//! default constructor
RotatedRect();
/*center:质心坐标
size:(x方向上全边长,y方向上全边长)
angle:顺时针偏角
*/
RotatedRect(const Point2f& center, const Size2f& size, float angle);
/**
三点确定一矩形,记得要互相垂直
*/
RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3);
/** 返回四个角点坐标,要用Point2f类型的数组对象作为参数传入,不能是仅仅是Point类型的数组对象*/
void points(Point2f pts[]) const;
//! returns the minimal up-right integer rectangle containing the rotated rectangle
Rect boundingRect() const;
//! returns the minimal (exact) floating point rectangle containing the rotated rectangle, not intended for use with images
Rect_<float> boundingRect2f() const;
//! returns the rectangle mass center
Point2f center;
//! returns width and height of the rectangle
Size2f size;
//! returns the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle.
float angle;
};
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
namedWindow("xuenai_rotate");
Mat xuenai_rotate(xuenai.size(), xuenai.type());
createTrackbar("angle","xuenai_rotate", nullptr,360);
while (1) {
int angle= getTrackbarPos("angle","xuenai_rotate");
Mat M = getRotationMatrix2D(Point2f(xuenai.cols / 2, xuenai.rows / 2), angle, 1);
warpAffine(xuenai, xuenai_rotate, M, xuenai.size());
imshow("xuenai_rotate",xuenai_rotate);
waitKey(20);
}
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat templ= imread("xuenai_rect.jpg");
imshow("template",templ);
Mat match_result;
matchTemplate(xuenai,templ,match_result,TM_SQDIFF);
Point temLoc;
Point minLoc;
Point maxLoc;
double min,max;
minMaxLoc(match_result,&min,&max,&minLoc,&maxLoc);
temLoc=minLoc;
rectangle(xuenai,Rect(temLoc.x,temLoc.y,templ.cols,templ.rows),Scalar(0,0,255));
imshow("xuenai_match",xuenai);
waitKey();
8.1.5 模板匹配的缺陷
无法应对旋转
Mat xuenai = imread("xuenai.jpg");
rotate(xuenai,xuenai,ROTATE_90_CLOCKWISE);
imshow("xuenai",xuenai);
Mat templ= imread("xuenai_rect.jpg");
Mat match_result;
matchTemplate(xuenai,templ,match_result,TM_SQDIFF);
Point temLoc;
Point minLoc;
Point maxLoc;
double min,max;
minMaxLoc(match_result,&min,&max,&minLoc,&maxLoc);
temLoc=minLoc;
rectangle(xuenai,Rect(temLoc.x,temLoc.y,templ.cols,templ.rows),Scalar(0,0,255));
imshow("xuenai_match",xuenai);
waitKey();
无法应对缩放
Mat xuenai = imread("xuenai.jpg");
resize(xuenai,xuenai,Size(500,500));
imshow("xuenai",xuenai);
Mat templ= imread("xuenai_rect.jpg");
Mat match_result;
matchTemplate(xuenai,templ,match_result,TM_SQDIFF);
Point temLoc;
Point minLoc;
Point maxLoc;
double min,max;
minMaxLoc(match_result,&min,&max,&minLoc,&maxLoc);
temLoc=minLoc;
rectangle(xuenai,Rect(temLoc.x,temLoc.y,templ.cols,templ.rows),Scalar(0,0,255));
imshow("xuenai_match",xuenai);
waitKey();
CV_EXPORTS_W void drawKeypoints( InputArray image, const std::vector<KeyPoint>& keypoints, InputOutputArray outImage,
const Scalar& color=Scalar::all(-1), DrawMatchesFlags flags=DrawMatchesFlags::DEFAULT );
enum struct DrawMatchesFlags
{
DEFAULT = 0, //!< Output image matrix will be created (Mat::create),
//!< i.e. existing memory of output image may be reused.
//!< Two source image, matches and single keypoints will be drawn.
//!< For each keypoint only the center point will be drawn (without
//!< the circle around keypoint with keypoint size and orientation).
DRAW_OVER_OUTIMG = 1, //!< Output image matrix will not be created (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.
};
CV_WRAP static Ptr<FastFeatureDetector> create( int threshold=10,
bool nonmaxSuppression=true,
FastFeatureDetector::DetectorType type=FastFeatureDetector::TYPE_9_16 );
CV_WRAP static Ptr<ORB> create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31,
int firstLevel=0, int WTA_K=2, ORB::ScoreType scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold=20);