前言:跟着浅墨大神,学习OpenCV3后,笔记如下。
Mat image = imread("E:/result/MyPic1.png", 0); //路径,0代表灰度打开
imshow("image1", image);
Mat gray_image;
cvtColor(image, gray_image, COLOR_BGR2GRAY); //转换色彩空间
imshow("out_gray_image", gray_image);
imwrite("E:/result/Mypic1_opencv.jpg", gray_image); //保存图片
void showCamera()
{
VideoCapture capture(0); //从摄像头中读取视频
while (true)
{
Mat frame;
capture >> frame;
namedWindow("读取视频");
imshow("读取视频", frame);
waitKey(30);
}
}
void showCapture()
{
VideoCapture capture;
capture.open("E:/result/MyVid.avi");
while (true)
{
Mat frame;
capture >> frame; //读取当前帧
if (frame.empty())
{
break;
}
imshow("读取视频", frame);
waitKey(30); //30ms
}
}
void showImage()
{
Mat src, dst;
src = imread("E:/result/MyPic1.png");
//src = imread("E:/result/zkc2.jpg");
if (!src.data)
{
cout << "could not open this image..." << endl;
return;
}
imshow("【原图】input image", src);
Mat edge, grayImage;
cvtColor(src, grayImage, CV_BGR2GRAY);
blur(grayImage, edge, Size(3, 3));
Canny(edge, edge, 3, 9, 3);
imshow("【灰度】", grayImage);
imshow("【边缘检测】Canny", edge);
}
createTrackbar()
int createTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange=0,void* userdata=0);
【示例】
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
using namespace cv;
using namespace std;
//-----------------------------------【全局函数声明部分】-----------------
// 描述:全局函数声明
//--------------------------------------------------------------------
Mat img;
int threshval = 160; //轨迹条滑块对应的值,给初值160
//-----------------------------【on_trackbar( )函数】-------------------
// 描述:轨迹条的回调函数
//--------------------------------------------------------------------
static void on_trackbar(int, void*)
{
Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);
//定义点和向量
vector > contours;
vector hierarchy;
//查找轮廓
findContours( bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
//初始化dst
Mat dst = Mat::zeros(img.size(), CV_8UC3);
//开始处理
if( !contours.empty() && !hierarchy.empty() )
{
//遍历所有顶层轮廓,随机生成颜色值绘制给各连接组成部分
int idx = 0;
for( ; idx >= 0; idx = hierarchy[idx][0] )
{
Scalar color( (rand()&255), (rand()&255), (rand()&255) );
//绘制填充轮廓
drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );
}
}
//显示窗口
imshow( "Connected Components", dst );
}
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main( )
{
system("color 5F");
//载入图片
img = imread("1.jpg", 0);
if( !img.data ) { printf("Oh,no,读取img图片文件错误~! \n"); return -1; }
//显示原图
namedWindow( "Image", 1 );
imshow( "Image", img );
//创建处理窗口
namedWindow( "Connected Components", 1 );
//创建轨迹条
createTrackbar( "Threshold", "Connected Components", &threshval, 255, on_trackbar );
on_trackbar(threshval, 0);//轨迹条回调函数
waitKey(0);
return 0;
}
//二维坐标系下点
Point point;
point.x = 10;
point.y = 8;
//或者
Point point = Point(10, 8);
//Scalar()具有4个元素的数组,最后一个可以不用,前三个表示BGR
Scalar(a, b, c); //a->B b->G c->R
Size s1 = Size(5, 5); //构造Size宽5,高5,即xxx.width 和 xxx.height 均5
//Rect包含左上角点坐标x,y 矩形的宽度width和高度height
//contains(Point) 判断点是否在内
//inside(Rect) 判断矩形是否在内
//tl()返回左上角坐标;
//br()返回右下角坐标;
Rect rect = rect1 & rect2; //交集
Rect rect = rect1 | rect2; //并集
Rect rectShift = rect + point; //平移
Rect rectScale = rect + size; //缩放
//函数原型 输入图,输出图,颜色转换标识符,通道数(默认保持不变)
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0);
cvtColor(srcImage, dstImage, COLOR_BGR2GRAY); //转换为灰度图
Matx轻量级的Mat
Vec是Matx派生类,一维的
Range
Matx23f image1; //2*3float类型的Matx
Range:all(); //其实就是MATLAB里的符号
Range(a, b); //就是MATLAB中的a:b
OpenCV中防止溢出的函数
alignPtr、alignSize、allocate、deallocate、fastMalloc、fastFree
include
计算向量角度函数 fastAtan2
计算立方根函数 cubeRoot
向上取整函数 cvCeil
向下取整函数 cvFloor
四舍五入函数 cvRound
判断自变量是否无穷大 cvIsInf
判断自变量是否不是一个数 cvIsNaN
显示文字函数 getTextSize、cvInitFont、putText
作图相关函数 circle、clipLine、ellipse、ellipse2Poly、line、rectangle、polylines、类LineIterator
填充相关函数 fillConvexPoly、fillPoly
OpenCv中RNG()函数作用为初始化随机数状态生成器
void DrawEllopse(Mat img, double angele); //绘制椭圆
void DrawFilledCircle(Mat img, Point center); //绘制实心圆
void DrawPolygon(Mat img); //绘制凸多边形
void DrawLine(Mat img, Point start, Point end); //绘制直线
//绘制椭圆
void DrawEllipse(Mat img, double angle)
{
int thickness = 2;
int lineType = 8;
ellipse(img,
Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2), //椭圆的中心点坐标
Size(WINDOW_WIDTH / 4, WINDOW_WIDTH / 16), //在这个大小的矩形内
angle, //椭圆旋转角度
0,
360,
Scalar(255, 129, 0), //BGR蓝色
thickness, //线宽2
lineType //线型8,联通线型
);
}
void DrawFilledCircle(Mat img, Point center)
{
int thinkness = -1;
int lineType = 8;
circle(img,
center, //圆心
WINDOW_WIDTH / 32, //半径
Scalar(0, 0, 255), //颜色
thinkness, //线宽-1,故为实心圆
lineType);
}
void DrawPolygon(Mat img)
{
int lineType = 8;
//Creat points
Point rookPoints[1][20];
rookPoints[0][0] = Point(WINDOW_WIDTH/4, 7* WINDOW_WIDTH/8);
rookPoints[0][1] = Point(3*WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8);
rookPoints[0][2] = Point(3*WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);
rookPoints[0][3] = Point(11*WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16);
rookPoints[0][4] = Point(19*WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8);
rookPoints[0][5] = Point(3*WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);
rookPoints[0][6] = Point(3*WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);
rookPoints[0][7] = Point(26*WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);
rookPoints[0][8] = Point(26*WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);
rookPoints[0][9] = Point(22*WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);
rookPoints[0][10] = Point(22*WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);
rookPoints[0][11] = Point(18*WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);
rookPoints[0][12] = Point(18*WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);
rookPoints[0][13] = Point(14*WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);
rookPoints[0][14] = Point(14*WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);
rookPoints[0][15] = Point(WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);
rookPoints[0][16] = Point(WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);
rookPoints[0][17] = Point(13*WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8);
rookPoints[0][18] = Point(5*WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16);
rookPoints[0][19] = Point(WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);
const Point* ppt[1] = { rookPoints[0] };
int npt[] = { 20 };
fillPoly(img,
ppt, //多边形顶点集
npt, //多边形顶点数目
1, //绘制的数量
Scalar(255, 255, 255), //颜色:白色
lineType);
}
void DrawLine(Mat img, Point start, Point end)
{
int thinckness = 2;
int lineType = 8;
line(img,
start,
end,
Scalar(0, 0, 0),
thinckness,
lineType);
3.5 main()
#include
#include
#include
#define WINDOW_WIDTH 600
#define WINDOW_NAME1 "【绘制图1】"
#define WINDOW_NAME2 "【绘制图2】"
using namespace std;
using namespace cv;
void DrawEllipse(Mat img, double angele); //绘制椭圆
void DrawFilledCircle(Mat img, Point center); //绘制实心圆
void DrawPolygon(Mat img); //绘制凸多边形
void DrawLine(Mat img, Point start, Point end); //绘制直线
int main()
{
Mat atomImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);
Mat rookImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);
//1.1 绘制椭圆
DrawEllipse(atomImage, 90);
DrawEllipse(atomImage, 0);
DrawEllipse(atomImage, 45);
DrawEllipse(atomImage, -45);
//1.2 绘制圆心
DrawFilledCircle(atomImage, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2));
//2.1 绘制多边形
DrawPolygon(rookImage);
//2.2 绘制矩形
rectangle(rookImage,
Point(0, 7*WINDOW_WIDTH / 8),
Point(WINDOW_WIDTH, WINDOW_WIDTH),
Scalar(0, 255, 255),
-1,
8);
//2.3绘制一些线段
DrawLine(rookImage, Point(0, 15*WINDOW_WIDTH / 16),
Point(WINDOW_WIDTH, 15* WINDOW_WIDTH / 16));
DrawLine(rookImage, Point(WINDOW_WIDTH / 4, 7*WINDOW_WIDTH / 8),
Point(WINDOW_WIDTH / 4, WINDOW_WIDTH));
DrawLine(rookImage, Point(WINDOW_WIDTH / 2, 7*WINDOW_WIDTH / 8),
Point(WINDOW_WIDTH / 2, WINDOW_WIDTH));
DrawLine(rookImage, Point(3*WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8),
Point(3*WINDOW_WIDTH / 4, WINDOW_WIDTH));
//3.1 showImage
imshow(WINDOW_NAME1, atomImage);
moveWindow(WINDOW_NAME1, 0, 200);
imshow(WINDOW_NAME2, rookImage);
moveWindow(WINDOW_NAME2, WINDOW_WIDTH, 200);
waitKey();
return 0;
}
//0~9 ->0;10~19->10
int divideWith = 10;
uchar table[256];
for(int i = 0; i < 256; i++)
{
table[i] = divideWith * (i / divideWith);
}
//建立Mat性用于查表
Mat lookUpTable(1, 256, CV_8U);
uchar* p = lookUpTable.data;
for (int i = 0; i < 256; i++)
p[i] = table[i];
//调用函数(I是输入,J是输出)
for (int i = 0; i < times; i++)
LUT(I, lookUpTable, J);
double time0 = static_cast(getTickCount()); //记录起始时间
// **** 图像操作 *** //
time0 = ((double)getTickCount() - time0) / getTickFrequency();
cout << "图像操作运行时间为:" << time0 << "秒" << endl; //输出运行时间
主程序 main
把256种颜色缩减成64种颜色
#include
#include
#include
#include //模块
#include //图像处理头文件
using namespace std;
using namespace cv;
void colorReduce(Mat & inputImage, Mat & outputImage, int div);
int main()
{
//1.创建原图并显示
Mat srcImage = imread("E:/result/MyPic1.png");
imshow("原始图像", srcImage);
//2.按照原图参数创建效果图
Mat dstImage;
dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());
//3.记录起始时间
double time0 = static_cast(getTickCount());
//4.调用颜色空间缩减函数
colorReduce(srcImage, dstImage, 32);
//5.计算运行时间并输出
time0 = ((double)getTickCount() - time0) / getTickFrequency();
cout << "图像操作运行时间为:" << time0 << "秒" << endl;
//6.显示效果图
imshow("效果图", dstImage);
waitKey();
return 0;
}
1.指针访问
void colorReduce(Mat & inputImage, Mat & outputImage, int div)
{
outputImage = inputImage.clone(); //复制实参到临时变量
int rowNumber = outputImage.rows; //行数
int colNumber = outputImage.cols * outputImage.channels(); //列数*通道数 = 每一行元素个数
//双循环,遍历所有像素值
for (int i = 0; i < rowNumber; i++) //行循环
{
uchar * data = outputImage.ptr(i); //获取第i行的首地址
for (int j = 0; j < colNumber; j++) //列循环
{
data[j] = data[j] / div * div + div / 2;
}
}
}
2.迭代器访问
void colorReduce(Mat & inputImage, Mat & outputImage, int div)
{
outputImage = inputImage.clone();
//获取迭代器
Mat_::iterator it = outputImage.begin(); //初始位置的迭代器
Mat_::iterator itend = outputImage.end(); //终止位置的迭代器
//存取彩色图像像素
for (; it != itend; it++)
{
//处理每个像素
(*it)[0] = (*it)[0] / div * div + div / 2;
(*it)[1] = (*it)[1] / div * div + div / 2;
(*it)[2] = (*it)[2] / div * div + div / 2;
}
}
3 动态地址
void colorReduce(Mat & inputImage, Mat & outputImage, int div)
{
outputImage = inputImage.clone();
int rowNumber = outputImage.rows;
int colNumber = outputImage.cols;
//存取彩色图像像素
for (int i = 0; i < rowNumber; i++)
{
for (int j = 0; j < colNumber; j++)
{
outputImage.at(i, j)[0] =
outputImage.at(i, j)[0] / div * div + div / 2; //蓝色通道
outputImage.at(i, j)[1] =
outputImage.at(i, j)[1] / div * div + div / 2; //绿色通道
outputImage.at(i, j)[2] =
outputImage.at(i, j)[2] / div * div + div / 2; //红色通道
}
}
}
Mat srcImage = imread...
Mat logo = imread...
Mat imageROI = srcImage(Rect(500, 250, logo.cols, logo.rows)); //img的ROI
Mat mask = imread("E:/pic.png", 0); //必须灰度图
logo.copyTo(imageROI, mask);
计算数组加权和addWeighted()函数
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);
//输入1,权重1,输入2(与1类型同),权重2,gamma,输出,默认深度同。
//内部操作如下
dst = src1[I]*alpha + src2[I]*beta + gamma;
void split(const Mat& src, Mat* mvbegin);
void split(InputArray m, OutputArrayOfArrays mv);
基础示例
vector channels;
Mat imageBlueChannel, imageGreenChannel, imageRedChannel;
srcImage = imread("MyPic");
//三通道图像转换成3个单通道图像
split(srcImage, channels); //分离颜色通道
imageBlueChannel = channels.at(0);
imageGreenChannel = channels.at(1);
imageRedChannel = channels.at(2);
void merge(const Mat& mv, size_tcont, OutputArray dst);
void merge(InputArrayOfArrays mv, OutputArray dst);
Mat srcImage = imread("1.png");
Mat imageBlueChannel, imageGreenChannel, imageRedChannel, mergeImage;
//三通道图像转换成3个单通道图像
split(srcImage, channels); //分离颜色通道
imageBlueChannel = channels.at(0);
imageGreenChannel = channels.at(1);
imageRedChannel = channels.at(2);
//对拆分的通道进行合并
merge(channels, mergeImage);
访问BGR像素
g(x) = a*f(x) + b
for (int y = 0; y < image.rows; y++)
{
for (int x = 0; x < image.cols; x++)
{
for (int c = 0; c < 3; c++)
{
new_image.at(y, x)[c] =
saturate_cast((g_nContrastValue*0.01)*(image.at(y, x)[c])
+ g_nBrightValue);
}
}
}
//saturate_cast 保护防止溢出
#include
#include
#include
#include
using namespace std;
using namespace cv;
static void on_ContrastAndBright(int, void *); //改变图像对比度和亮度值的回调函数
//static void ShowHelpText();
int g_nContrastValue; //对比度
int g_nBrightValue; //亮度值
Mat g_srcImage, g_dstImage;
int main()
{
//【1】读取输入图像
g_srcImage = imread("E:/result/MyPic.png");
if (!g_srcImage.data) { cout << "读取g_srcImage error~"; return false; }
g_dstImage = Mat::zeros(g_srcImage.size(), g_srcImage.type());
//【2】设置对比度和亮度
g_nBrightValue = 80;
g_nContrastValue = 80;
//【3】创建效果图窗口
namedWindow("【效果图窗口】", 1);
//【4】创建轨迹条
createTrackbar("对比度", "【效果图窗口】", &g_nContrastValue,
300, on_ContrastAndBright);
createTrackbar("亮 度", "【效果图窗口】", &g_nBrightValue,
200, on_ContrastAndBright);
//【5】进行回调函数初始化
on_ContrastAndBright(g_nContrastValue, 0);
on_ContrastAndBright(g_nBrightValue, 0);
//【6】按下"q",程序退出
while(char(waitKey(1)) != 'q'){}
destroyAllWindows();
return 0;
}
static void on_ContrastAndBright(int, void *)
{
cvNamedWindow("【原图窗口】", 1);
//for计算:g_dstImage(i, j) = a*g_dstImage(i, j) + b
for (int y = 0; y < g_srcImage.rows; y++)
{
for (int x = 0; x < g_srcImage.cols; x++)
{
for (int c = 0; c < 3; c++)
{
g_dstImage.at(y, x)[c] =
saturate_cast((g_nContrastValue*0.01)*(g_srcImage.at(y, x)[c])
+ g_nBrightValue);
}
}
}
imshow("【原图窗口】", g_srcImage);
imshow("【效果图窗口】", g_dstImage);
}
对一维或二维浮点数进行正向和反向离散傅立叶变换
void dft(InputArray src, OutputArray dst, int flages = 0, int nonzeroRows = 0)
//参数3->变换类型(默认正变换);参数4->最好是要处理的行C.rows
dft()函数计算两个二维实矩阵卷积的示例核心片段
void convolveDFT(InputArray A, InputArray B, OutputArray C)
{
//【1】初始化输出矩阵
C.create(abs(A.rows - B.rows) + 1, abs(A.cols - B.cols) + 1, A.type());
Size dftSize;
//【2】计算DFT变换的尺寸
dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);
dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1);
//【3】分配临时缓冲区并初始化为零
Mat tempA(dftSize, A.type(), Scalar::all(0));
Mat tempB(dftSize, B.type(), Scalar::all(0));
//【4】分别复制A和B到tempA和tempB的左上角
Mat roiA(tempA, Rect(0, 0, A.cols, A.rows));
A.copyTo(roiA);
Mat roiB(tempB, Rect(0, 0, B.cols, B.rows));
B.copyTo(roiB);
//【5】就地操作(in-place),快速傅立叶变换,并将nonzeroRows参数置为非零
dft(tempA, tempA, 0, A.rows);
dft(tempB, tempB, 0, B.rows);
//【6】将得到的频谱相乘,结果放在tempA中
mulSpectrums(tempA, tempB, tempA, 0);
//【7】将结果变换为频域,且结果行(result rows)都为非零
//我们只需要其中的C.rows的第一行,所以采用nonzeroRows == C.rows
dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, C.rows);
//【8】将结果复制到C中
tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C);
//所有的临时缓冲区将被自动释放,无需收尾工作
}
返回给定向量尺寸的傅立叶最优尺寸大小
int 类型的 vecsize, 向量尺寸,即图片的rows、cols
int getOptimalDEFSize(int vecsize);
void copyMakeBorder(InputArray src, OutputArray dst, int top, int bottom, int left, int right, int borderType, const Scalar& value = Scalar());
void magnitude(InputArray x, InputArray y, OutputArray magnitude
);
void log(InputArray src, OutputArray dst);
void normalize(InputArray src, OutputArray dst, double alpha = 1,
double beta = 0, int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray())
imgproc组件是Image和Process组合
方框滤波(box Filter)被封装在一个名为boxblur的函数中,作用是模糊一张图片
void boxFilter(InputArray src,OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), boolnormalize=true, int borderType=BORDER_DEFAULT)
均值滤波是方框滤波归一化后的特殊情况。
如果我们要在可变的窗口中计算像素总和,可以使用integral()函数。
破坏了细节
void blur(InputArray src, OutputArraydst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
第三个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小。
第四个参数:默认中心点为目标点。
void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )
medianBlur( InputArray src,OutputArray dst, int ksize )
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 );
Mat g_srcImage, g_dstImage;
//双边滤波参数值
int g_nBilateralFilterValue = 10;
//轨迹条回调函数 -
static void on_BilateralFilter(int, void *);
int main()
{
g_srcImage = imread("E:/result/MyPic.png", 1);
if (!g_srcImage.data)
{
cout << "读取错误" << endl;
return 0;
}
//复制原图
g_dstImage = g_srcImage.clone();
namedWindow("【原图】双边滤波", 1);
imshow("【原图】双边滤波", g_srcImage);
//双边滤波操作
namedWindow("【效果图】双边滤波", 1);
createTrackbar("value:", "【效果图】双边滤波", &g_nBilateralFilterValue,
50, on_BilateralFilter);
on_BilateralFilter(g_nBilateralFilterValue, 0);
waitKey(0);
return 0;
}
//回调函数
static void on_BilateralFilter(int, void *)
{
bilateralFilter(g_srcImage, g_dstImage, g_nBilateralFilterValue,
g_nBilateralFilterValue * 2, g_nBilateralFilterValue / 2);
imshow("【效果图】双边滤波", g_dstImage);
}
腐蚀和膨胀是对***白色部分(高亮部分***)而言的,不是黑色部分。
膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。
void dilate(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);
第三个参数,InputArray类型的kernel,膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核。
我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。
其中,getStructuringElement函数的第一个参数表示内核的形状,可以选择如下三种形状之一:
而getStructuringElement函数的第二和第三个参数分别是内核的尺寸以及锚点的位置。
我们一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得getStructuringElement函数的返回值。
对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心。且需要注意,十字形的element形状唯一依赖于锚点的位置。而在其他情况下,锚点只是影响了形态学运算结果的偏移。
getStructuringElement函数相关的调用示例代码如下:
int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT,
Size(2*g_nStructElementSize+1,2*g_nStructElementSize+1),
Point( g_nStructElementSize, g_nStructElementSize ));
【膨胀核心代码】
//载入原图
Mat image = imread("1.jpg");
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat out;
//进行膨胀操作
dilate(image, out, element);
参数列表与6.1相同
【腐蚀核心代码】
//载入原图
Mat image = imread("1.jpg");
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat out;
//进行腐蚀操作
erode(image,out, element);
先腐蚀后膨胀的过程
开运算可以用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。
先膨胀后腐蚀的过程
排除小型黑洞(黑色区域)
膨胀图与腐蚀图之差
对二值图像进行这一操作可以将团块(blob)的边缘突出出来
原图像与“开运算“的结果图之差
顶帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。
”闭运算“的结果图与原图像之差
分离比邻近点暗一些的斑块
void morphologyEx(
InputArray src,
OutputArray dst,
int op,
InputArraykernel,
Pointanchor=Point(-1,-1),
intiterations=1,
intborderType=BORDER_CONSTANT,
constScalar& borderValue=morphologyDefaultBorderValue() );
MORPH_OPEN – 开运算(Opening operation)
MORPH_CLOSE – 闭运算(Closing operation)
MORPH_GRADIENT -形态学梯度(Morphological gradient)
MORPH_TOPHAT - “顶帽”(“Top hat”)
MORPH_BLACKHAT - “黑帽”(“Black hat“)
MORPH_ERODE - 腐蚀
MORPH_DILATE - 膨胀
getS参数一:
【getS示例】
int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸
//获取自定义核
Mat element =getStructuringElement(MORPH_RECT,
Size(2*g_nStructElementSize+1,2*g_nStructElementSize+1),
Point(g_nStructElementSize, g_nStructElementSize ));
//定义核[常用版本]
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
用特定的颜色填充联通区域
标记或分离图像的一部分以便对其进行进一步处理或分析
int floodFill(InputOutputArray image, InputOutputArray mask, Point seedPoint,Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 )
* **resize() 缩放**
* **pyrUp() 向上采样(高斯金字塔) -- 尺寸加倍**
* **pyrDown() 向下采样(拉普拉斯金字塔)**
resize() 函数
void resize(InputArray src,OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )
INTER_NEAREST - 最近邻插值
INTER_LINEAR - 线性插值(默认值)
INTER_AREA - 区域插值(利用像素区域关系的重采样插值)
INTER_CUBIC –三次样条插值(超过4×4像素邻域内的双三次插值)
INTER_LANCZOS4 -Lanczos插值(超过8×8像素邻域的Lanczos插值)
若要缩小图像,一般情况下最好用CV_INTER_AREA来插值,
而若要放大图像,一般情况下最好用INTER_CUBIC(效率不高,慢,不推荐使用)或INTER_LINEAR(效率较高,速度较快,推荐使用)。
【方式一:设定目标尺寸】
Mat dst=Mat::zeros(512 ,512, CV_8UC3 );//新建一张512x512尺寸的图片
Mat src=imread(“1.jpg”);
//显式指定dsize=dst.size(),那么fx和fy会其计算出来,不用额外指定。
resize(src, dst, dst.size());
【方式二:设定放缩因子】
Mat dst;
Mat src=imread(“1.jpg”)
//指定fx和fy,让函数计算出目标图像的大小。
resize(src, dst, Size(), 0.5, 0.5); //x,y 缩放0.5
pyrUp() 向上采样(高斯金字塔) – 尺寸放大
void pyrUp(InputArray src, OutputArraydst, const Size& dstsize=Size(), int borderType=BORDER_DEFAULT )
pyrDown() 向下采样(拉普拉斯金字塔) – 尺寸缩小
void pyrDown(InputArray src,OutputArray dst, const Size& dstsize=Size(), int borderType=BORDER_DEFAULT)
根据灰度差异,选区出目标
- Threshold() 固定阈值操作
- adaptiveThreshold() 自适应阈值
Threshold() 固定阈值操作
典型应用于灰度图处理,得到二值图像
double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)
参数三:具体的阈值。
adaptiveThreshold() 自适应阈值
void adaptThresholde(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
* **Canny 算子**
* **Sobel 算子**
* **Laplacian 算子**
* **Scharr 滤波器**
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);
Sobel 算子是一个主要用作边缘检测的离散微分算子 (discrete differentiation operator)。 Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。
在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。
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 );
void Laplacian(InputArray src,OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, intborderType=BORDER_DEFAULT );
使用Scharr滤波器运算符计算x或y方向的图像差分。
其实它的参数变量和Sobel基本上是一样的,除了没有ksize核的大小。
void Scharr(
InputArray src, //源图
OutputArray dst, //目标图
int ddepth,//图像深度
int dx,// x方向上的差分阶数
int dy,//y方向上的差分阶数
double scale=1,//缩放因子
double delta=0,// delta值
intborderType=BORDER_DEFAULT )// 边界模式
<1>标准霍夫变换(StandardHough Transform,SHT),由HoughLines函数调用。
<2>多尺度霍夫变换(Multi-ScaleHough Transform,MSHT),由HoughLines函数调用。
<3>累计概率霍夫变换(ProgressiveProbabilistic Hough Transform,PPHT),由HoughLinesP函数调用。
void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 )
void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )
oughCircles函数可以利用霍夫变换算法检测出灰度图中的圆
void HoughCircles(InputArray image,OutputArray circles, int method, double dp, double minDist, double param1=100,double param2=100, int minRadius=0, int maxRadius=0 )
镜像、翻转
* **旋转 rotation(线性变换)**
* **平移 translation(向量加)**
* **缩放 scale(线性变换)**
void equalizeHist(InputArray src, OutputArray dst)
用于二值图像中寻找轮廓
vector> contours; //轮廓
vector hierarchy; //层次结构
绘制外部/内部轮廓
//返回Rect
//返回RotatedRect
//返回RotatedRect
//返回Moments
//返回double
//返回double
#include
#include
#include
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main(int argc, char** argv)
{
Mat src = imread("1.jpg", IMREAD_GRAYSCALE);
if (src.empty()) { cout << "load error!" << endl; return -1; }
namedWindow("input image", WINDOW_AUTOSIZE);
imshow("input image", src);
//SURF特征检测
int minHessian = 400;
Ptr detector = SURF::create(minHessian);
vector keypoints;
detector->detect(src, keypoints, Mat());
//绘制关键点
Mat keypoint_img;
drawKeypoints(src, keypoints, keypoint_img, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
imshow("keypoints", keypoint_img);
waitKey(0);
return 0;
}
#include
#include
#include
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main(int argc, char** argv)
{
Mat src = imread("1.jpg", IMREAD_GRAYSCALE);
if (src.empty()) { cout << "load error!" << endl; return -1; }
namedWindow("input image", WINDOW_AUTOSIZE);
imshow("input image", src);
//SIF特征检测
int numFeatures = 100;
Ptr detector = SIFT::create(numFeatures);
vector keypoints;
detector->detect(src, keypoints, Mat());
//绘制
Mat keypoints_img;
drawKeypoints(src, keypoints, keypoints_img, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
namedWindow("SIFT - OUT", WINDOW_AUTOSIZE);
imshow("SIFT - OUT", keypoints_img);
waitKey(0);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oa46OTck-1582962531761)(https://uploader.shimo.im/f/bGxaBSZQO1oCcd8A.png!thumbnail)]
BFMacher matcher(NORM_L2);
//FlannBasedMatcher matcher;
FlannBasedMatcher matcher(new flann::LshIndexParams(20, 10, 2));
Ptr detector = AKAZE::create();
Ptr detector = BRISK::create();
Ptr detector = BRISK::create();
vector keypoints;
detector->detect(srcImage1, keypoints, Mat());
Mat resultImg;
drawKeypoints(srcImage1, keypoints, resultImg);
imshow("resultImg", resultImg);
#include
#include
#include
#include
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main(int argc, char** argv)
{
String cascadeFilePath = "D:/opencv/build/etc/haarcascades/haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;
if (!face_cascade.load(cascadeFilePath))
{
cout << "could not load haar dara.." << endl;
return -1;
}
Mat src, src_gray;
src = imread("E:/result/666.jpg", IMREAD_COLOR);
cvtColor(src, src_gray, COLOR_BGR2GRAY);
//imshow("原图", src);
equalizeHist(src_gray, src_gray);
vector faces;
face_cascade.detectMultiScale(src_gray, faces, 1.1, 2, 0);
for (size_t t = 0; t < faces.size(); t++)
{
rectangle(src, faces[t], Scalar(0, 0, 255), 2, 8, 0);
}
imshow("faces", src);
waitKey(0);
return 0;
}