本文章用于记录自己使用open CV过程中的要点,便于遗忘时查看。
首先使用
using namespace std;
using namespace cv;
避免每次都需要敲 ::cv及::std;
图像的读写显示存取
图像定义:
Mat image;
图像读取:
imread(const String & filename,int flags = IMREAD_COLOR);
支持格式有:
Windows bitmaps - *.bmp, *.dib (always supported)
JPEG files - *.jpeg, *.jpg, *.jpe (see the Notes section)
JPEG 2000 files - *.jp2 (see the Notes section)
Portable Network Graphics - *.png (see the Notes section)
WebP - *.webp (see the Notes section)
Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm (always supported)
Sun rasters - *.sr, *.ras (always supported)
TIFF files - *.tiff, *.tif (see the Notes section)
OpenEXR Image files - *.exr (see the Notes section)
Radiance HDR - *.hdr, *.pic (always supported)
Raster and Vector geospatial data supported by Gdal (see the Notes section)
读取方式有:
IMREAD_UNCHANGED 按照图片原格式读入.
IMREAD_GRAYSCALE 将图片转为单通道灰色图.
IMREAD_COLOR 将图片转为BGR3通道 .
IMREAD_ANYDEPTH 如果图片是16-bit/32-bit ,则保持不变,其他的都转为8-bit.
IMREAD_ANYCOLOR 图像以任何可能的颜色格式读取.
IMREAD_LOAD_GDAL 使用GDAL载入图像.
IMREAD_REDUCED_GRAYSCALE_2 将图片转为单通道灰色图,同时将图片尺寸裁剪到 1/2.
IMREAD_REDUCED_COLOR_2 将图片转为BGR 3通道,同时将图片尺寸裁剪到 1/2.
IMREAD_REDUCED_GRAYSCALE_4 将图片转为单通道灰色图,同时将图片尺寸裁剪到 1/4.
IMREAD_REDUCED_COLOR_4 将图片转为BGR 3通道,同时将图片尺寸裁剪到 1/4.
IMREAD_REDUCED_GRAYSCALE_8 将图片转为单通道灰色图,同时将图片尺寸裁剪到 1/8.
IMREAD_REDUCED_COLOR_8 将图片转为BGR 3通道,同时将图片尺寸裁剪到 1/8.
IMREAD_IGNORE_ORIENTATION 如果设置,不旋转图像根据EXIF的定位标志
显示图像:
imshow(const String & winname, InputArray mat);
显示窗口:
namedWindow(const String & winname,int flags = WINDOW_AUTOSIZE)
WINDOW_NORMAL设置了这个值,用户便可以改变窗口的大小
WINDOW_AUTOSIZE如果设置了这个值,窗口大小会自动调整以适应所显示的图像,并且不能手动改变窗口大小。
WINDOW_OPENGL 如果设置了这个值的话,窗口创建的时候便会支持OpenGL。
waitKey(int delay = 0)
这个函数用来等待,读取和处理事件。当我们没有输入,只需要窗口停留,就可以将参数设为0。
图像保存:
imwrite(const String & filename InputArray img, const vector< int > & params = vector< int >())
图像缩放、旋转、截取、叠加
缩放:
resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )
InputArray src -原图像
OutputArray dst -输出图像
Size dsize -目标图像的大小
double fx=0 -在x轴上的缩放比例
double fy=0 -在y轴上的缩放比例
int interpolation -插值方式,有以下四种方式
INTER_NN -最近邻插值
INTER_LINEAR -双线性插值 (缺省使用)
INTER_AREA -使用象素关系重采样,当图像缩小时候,该方法可以避免波纹出现。当图像放大时,类似于 INTER_NN 方法。
INTER_CUBIC -立方插值。
dsize与(fx,fy)不能同时为0
旋转:
Mat rotMat;Point rotCenter = Point(x,y); // x,y为旋转中心坐标
rotMat = getRotationMatrix2D(Point2f center, double angle, double scale);//获取旋转矩阵,angle为逆时针;scale为缩放比例.
warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar());
根据getAffineTransform或getRotationMatrix2D得到的变换矩阵,计算变换后的图像。
src为输入图像
dst为变换后图像,类型与src一致。
M为变换矩阵,需要通过其它函数获得,当然也可以手动输入。
dsize为输出图像的大小
flags,插值算法,详细如下:
INTER_NEAREST = 0, //最近邻插值
INTER_LINEAR = 1, //双线性插值
INTER_CUBIC = 2, //双三次插值
INTER_AREA = 3, //区域插值,使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。
INTER_LANCZOS4 = 4, //Lanczos插值(超过8×8像素邻域的Lanczos插值)
INTER_MAX = 7,
WARP_FILL_OUTLIERS = 8, //填充所有输出图像的象素
WARP_INVERSE_MAP = 16 //逆变换
borderMode为边界处理方式:
BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i`
BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
BORDER_REFLECT = 2, //!< `fedcba|abcdefgh|hgfedcb`
BORDER_WRAP = 3, //!< `cdefgh|abcdefgh|abcdefg`
BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
BORDER_TRANSPARENT = 5, //!< `uvwxyz|absdefgh|ijklmno`
BORDER_REFLECT101 = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
BORDER_DEFAULT = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
BORDER_ISOLATED = 16 //!< do not look outside of ROI
截取:
Mat imageROI;
imageROI = image(Rect(100, 100, 400, 400));
或者用:
imageROI = image(Range(100, 400),Range(100, 400));
叠加:
addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);
公式为: dst = src1*alpha + src2*beta + gamma;
注意:图像大小必须一致。如果不一致,可以用ROI方法:
首先在原图中取出需要添加的位置图像:
imageROI = image(Rect(200, 200, image_to_add.cols, image_to_add.rows));
然后将需要添加的图像融合:
addWeighted(image_to_add, 0.8, imageROI, 0.1, 0., imageROI);
这样需要叠加的图像 image_to_add 就添加到imageROI区域了。
直方图、梯度、滤波
直方图:
参考:点击打开链接
sobel算子计算梯度:
参考:点击打开链接
直方图均衡:
equalizeHist(InputArray src,
OutputArray dst
);
中值滤波:
blur(InputArray src,
OutputArray dst,
Size ksize,
Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT
);
高斯滤波:
GaussianBlur(InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY = 0,
int borderType = BORDER_DEFAULT
);
双边滤波:
bilateralFilter(InputArray src,
OutputArray dst,
int d,
double sigmaColor,
double sigmaSpace,
int borderType = BORDER_DEFAULT
);
方框滤波:
boxFilter(InputArray src,
OutputArray dst,
int ddepth,
Size ksize,
Point anchor = Point(-1,-1),
bool normalize = true,
int borderType = BORDER_DEFAULT
);
颜色空间转换
参考:点击打开链接
边缘、轮廓
用Sobel计算边缘
假定输入图像矩阵为 I,卷积核大小为 3x3,则水平一阶导数 Gx 和垂直一阶导数 Gy 分别为:
OpenCV 中,Sobel 函数如下:
void cv::Sobel (
InputArray src, // 输入图像
OutputArray dst, // 输出图像
int ddepth, // 输出图像深度,-1 表示等于 src.depth()
int dx, // 水平方向的阶数
int dy, // 垂直方向的阶数
int ksize = 3, // 卷积核的大小,常取 1, 3, 5, 7 等奇数
double scale = 1, // 缩放因子,应用于计算结果
double delta = 0, // 增量数值,应用于计算结果
int borderType = BORDER_DEFAULT // 边界模式
);
用Scharr卷积核计算:
当卷积核大小为 3x3 时,使用 sobel 卷积核来计算并不是很精确,此时常用 Scharr 卷积核来代替,如下:
而 Sharr 函数,本质上就是令 ksize = 3 且使用 Scharr 卷积核的 Sobel 函数。
void cv::Scharr (
InputArray src,
OutputArray dst,
int ddepth,
int dx,
int dy,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
);
对于 Scharr 函数,要求 dx 和 dy 都 >= 0 且 dx + dy == 1,假如 dx 和 dy 都设为 1,则会抛出异常。
因此,对于 Sobel 和 Scharr 函数,通常各自求其 x 和 y 方向的导数,然后通过加权来进行边缘检测。
用 Laplace算子计算:
void cv::Laplacian (
InputArray src,
OutputArray dst,
int ddepth,
int ksize = 1,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
);
用Canny算子计算:
Canny 边缘检测算子,其算法步骤大体如下:
1) 用高斯滤波器对输入图像做平滑处理 (大小为 5x5 的高斯核)
2) 计算图像的梯度强度和角度方向 ( x 和 y 方向上的卷积核)
角度方向近似为四个可能值,即 0, 45, 90, 135
3) 对图像的梯度强度进行非极大抑制
可看做边缘细化:只有候选边缘点被保留,其余的点被移除
4) 利用双阈值检测和连接边缘
若候选边缘点大于上阈值,则被保留;小于下阈值,则被舍弃;处于二者之间,须视其所连接的像素点,大于上阈值则被保留,反之舍弃
void cv::Canny (
InputArray image, // 输入图像 (8位)
OutputArray edges, // 输出图像 (单通道,8位)
double threshold1, // 下阈值
double threshold2, // 上阈值
int apertureSize = 3,
bool L2gradient = false
);
找出轮廓直线:
HoughLines( InputArray image,
OutputArray lines,//line[i][0]为半径,line[i][1]为角度.定义用 vector<Vec2f> lines;
double rho,//半径
double theta,//角度
int threshold,
double srn = 0,
double stn = 0,
double min_theta = 0,
double max_theta = CV_PI
);
例子参考:
Houghlines找出轮廓直线
找出闭合轮廓:
findContours(InputOutputArray image,
OutputArrayOfArrays contours,// vector<vector<Point>> contours;
OutputArray hierarchy,// vector<Vec4i> hierarchy
int mode, // CV_RETR_EXTERNAL只检测最外围轮廓
// CV_RETR_LIST 检测所有的轮廓,无等级
// CV_RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系
// CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构
int method, // CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内
// CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息
// CV_CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_TC89_KCOS
Point offset = Point()
————————————————
版权声明:本文为CSDN博主「benedict_tao」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/benedict_tao/article/details/79871150