void setMouseCallback(const String &winname, MouseCallback onMouse, void *userdata = 0);
返回值: 空
winname: 显示窗口的名字
onMouse: 鼠标响应回调函数
userdata: 给鼠标回调函数传递的任意类型的数据
回调函数的定义
void (*MouseCallback)(int event, int x, int y, int flags, void *userdata);
返回值:空
event: 鼠标事件 枚举类型
x: 鼠标在图片中x坐标
y:鼠标在图片中y坐标
flags: 标志位
userdata: 使用的资源
envnet 常用的类型
even 类型t | 意思 |
---|---|
EVENT_MOUSEMOVE | 鼠标移动 |
EVENT_LBUTTONDOWN | 鼠标左键按下 |
EVENT_RBUTTONDOWN | 鼠标右键按下 |
EVENT_MBUTTONDOWN | 鼠标滚轮按下 |
EVENT_LBUTTONUP | 鼠标左键抬起 |
EVENT_RBUTTONUP | 鼠标右键抬起 |
EVENT_MBUTTONUP | 鼠标滚轮抬起 |
EVENT_LBUTTONDBLCLK | 鼠标左键双击 |
EVENT_RBUTTONDBLCLK | 鼠标右键双击 |
EVENT_MBUTTONDBLCLK | 鼠标滚轮双击 |
EVENT_MOUSEWHEEL | 鼠标滚轮滑动,flags>0向前滚动,flags<0向后滚动 |
Point moveP(-1, -1);
Point downP(-1, -1);
int A=0;
//鼠标回调函数
void mouseMove(int event, int x, int y, int flags, void *userdata)
{
//把任意类型的数据转换成Mat类型
Mat src = *((Mat *) userdata);
//把src原图像克隆给dec
Mat dec = src.clone();
Mat dst;
//鼠标移动事件
if (event == EVENT_MOUSEMOVE)
{
moveP.x = x;
moveP.y = y;
//当左键按下,画出矩形块
if (downP.x != -1)
{
//定义矩形
Rect rect(downP,moveP);
rectangle(dec, rect, Scalar(0, 0, 255), 3);
imshow("输出窗口", dec);
}
cout << "x " << moveP.x << " y " << moveP.y << endl;
}
//鼠标左键按下
if (event == EVENT_LBUTTONDOWN)
{
downP.x = x;
downP.y = y;
cout << "x " << downP.x << " y " << downP.y << endl;
}
//鼠标左键抬起
if (event == EVENT_LBUTTONUP)
{
//校验鼠标坐标是否在图片范围内
if (moveP.x >= src.cols)
{
moveP.x = src.cols;
}
if (moveP.y >= src.rows)
{
moveP.y = src.rows;
}
if (moveP.x <= 0)
{
moveP.x = 0;
}
if (moveP.y <= 0)
{
moveP.y = 0;
}
Rect rect1(downP, moveP);
namedWindow("提取");
imshow("提取", dec(rect1));
downP.x = -1;
downP.y = -1;
}
if (event == EVENT_MOUSEWHEEL)
{
cout << "我是flage" << flags << endl;
//向前滚动
if (flags > 0)
{
A++;
resize(src, dst, Size(src.rows + A, src.cols + A));
} else
{
A--;
resize(src, dst, Size(src.rows + A, src.cols + A));
}
// cout << "srcRows " << srcRows << " srcCols " << srcCols << endl;
imshow("图片缩放", dst);
}
}
//鼠标事件
void mouseEvent(Mat &src)
{
namedWindow("输出窗口", WINDOW_FREERATIO);
setMouseCallback("输出窗口", mouseMove, &src);
imshow("输出窗口", src);
}
void flip(InputArray src, OutputArray dst, int flipCode);
返回值:空
src: 原图像
dst: 结果图像
flipCode: 翻转类型 flipCode<0 旋转180度
flipCode 类型
flipCode | 意思 |
---|---|
flipCode<0 | 旋转180度 |
flipCode=0 | 图像上下翻转 |
flipCode>0 | 图像左右翻转 |
例子: 翻转图像
void myFlip(Mat &src){
Mat dst;
flip(src, dst, -1);
imshow("旋转180", dst);
flip(src, dst, 0);
imshow("图像上下翻转", dst);
flip(src, dst, 1);
imshow("图像左右翻转", dst);
}
void warpAffine( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
返回值: 空
src: 原图片
dst: 结果图片
M : 仿射变换的变换矩阵
dsize :结果图片的大小
flags: 内插值类型
borderMode: 变换过后边界的类型
borderValue: 边界的颜色
仿射变换的公式
利用上述公式可以实现图片的平移
,旋转
,缩放
,剪切
等四种变换
其中A就是我们的API中的M
例子: 关于中心旋转
void myRotate(Mat &src)
{
//结果图片
Mat dst;
//仿射变换的矩阵
Mat M;
//图片的宽和高
double rows = src.rows;
double cols = src.cols;
/*
* 获得旋转的仿射变换矩阵
* 第一个参数表示: 绕那个点进行旋转,这里选择中心点
* 第二个参数表示: 旋转多少度 angle>0表示逆时针旋转 angle<0表示顺时针旋转
* 第三个参数表示: 结果图片是否进行缩放
*返回结果:是一个3X3的矩阵,参考上图(关于原点)选择的仿射矩阵A
**/
M = getRotationMatrix2D(Point2f(rows / 2, cols / 2), 45, 1.0);
//计算新图像的长宽高
double cos$ = abs(M.at<double>(0, 0));
double sin$ = abs(M.at<double>(0, 1));
double newRow = rows * cos$ + cols * sin$;
double newCol = cols * cos$ + rows * sin$;
//新图像的中心点
M.at<double>(0, 2) += (newRow - rows) / 2.0;
M.at<double>(1, 2) += (newCol - cols) / 2.0;
//进行仿射变换
warpAffine(src, dst, M, Size(newRow, newCol));
imshow("仿射变换", dst);
//缩放
Mat transform_scale = Mat::zeros(2, 3, CV_64F);
transform_scale.at<double>(0,0)=0.8;
transform_scale.at<double>(1,1)=0.8;
warpAffine(src, dst, transform_scale, Size(rows, cols), INTER_AREA, BORDER_CONSTANT, Scalar(0, 255, 255));
imshow("仿射变换--缩放", dst);
//平移
Mat transform_T = Mat::zeros(2, 3, CV_64F);
transform_T.at<double>(0,0)=1;
transform_T.at<double>(1,1)=1;
transform_T.at<double>(0,2)=100;
transform_T.at<double>(1,2)=100;
warpAffine(src, dst, transform_T, Size(rows, cols), INTER_AREA, BORDER_CONSTANT, Scalar(0, 255, 255));
imshow("仿射变换--平移", dst);
//剪切
Mat transform_C = Mat::zeros(2, 3, CV_64F);
transform_C.at<double>(0,0)=1;
transform_C.at<double>(1,1)=1;
transform_C.at<double>(1,0)=0.5;
transform_C.at<double>(0,1)=0.5;
warpAffine(src, dst, transform_C, Size(rows, cols), INTER_AREA, BORDER_CONSTANT, Scalar(0, 255, 255));
imshow("仿射变换--剪切", dst);
return ;
return ;
}
void calcHist( const Mat* images, int nimages,
const int* channels, InputArray mask,
OutputArray hist, int dims, const int* histSize,
const float** ranges, bool uniform = true, bool accumulate = false );
返回值:空
images: 原图像
nimages: 原图像的数量
channels:原图像的通道数
mask:若要计算整个图像则mask=Mat()空图像,若要计算一部分图像则需要不为空
hist:输出的结果
dims:直方图的维数
histSize:直方图的个数(若是柱形图则表示有几个柱形,折线图则表示有几个转折点)
ranges:统计灰度的范围
uniform:是否对得到的直方图数组进行归一化处理 默认为true
accumulate :在多个图像时,是否累计计算像素值得个数 默认为false
void newMyhistogram(Mat &src)
{
//分离通道
vector<Mat> bgr_plane;
split(src, bgr_plane);
//柱状图的个数
const int binSize[1] = {
255};
//统计灰度的范围
float hRanges[2] = {
0, 255};
const float *ranges[1] = {
hRanges};
//得到的GBR的灰度统计的直方图
Mat b_hist;
Mat g_hist;
Mat r_hist;
calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, binSize, ranges);
calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, binSize, ranges);
calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, binSize, ranges);
//创建输出图像
int hist_w = 512;
int hist_h = 400;
int bin_w = cvRound((double) hist_w / binSize[0]);
Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
//绘制 直方图
for (int i = 0; i < 256; i++)
{
line(histImage, Point(bin_w * i, cvRound((double) hist_h - b_hist.at<float>(i))),
Point(bin_w * (i + 1), cvRound((double) hist_h - b_hist.at<float>(i + 1))),
Scalar(255, 0, 0), 2, LINE_8,0);
line(histImage, Point(bin_w * i, cvRound((double) hist_h - g_hist.at<float>(i))),
Point(bin_w * (i + 1), cvRound((double) hist_h - g_hist.at<float>(i + 1))),
Scalar(0, 255, 0), 2, LINE_8,0);
line(histImage, Point(bin_w * i, cvRound((double) hist_h - r_hist.at<float>(i))),
Point(bin_w * (i + 1), cvRound((double) hist_h - r_hist.at<float>(i + 1))),
Scalar(0, 0, 255), 2, LINE_8,0);
cout << "我是数值 " << b_hist.at<float>(i) << endl;
}
imshow("直方图", histImage);
}
void equalizeHist( InputArray src, OutputArray dst );
返回值:空
src: 原图像
dst: 结果图像
void eqmynewHistorgram(Mat &src)
{
//转换成灰度图像
cvtColor(src, src, COLOR_BGR2GRAY);
Mat dst;
//直方图均衡化
equalizeHist(src, dst);
namedWindow("直方图均值化", WINDOW_FREERATIO);
imshow("直方图均值化", dst);
}
直方图均值化有利于提高图像的对比度,为了证明这一说法我们来看一组图片
从上述的图片当中,我们可以看高对比度的直方图的像素灰度值分布的比较均已,而我们的直方图均衡化就是把我们的原图像素灰度值进行均衡化
void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
double sigmaX, double sigmaY = 0,
int borderType = BORDER_DEFAULT );
返回值: 空
src:原图像
dst: 结果图像
ksize:模糊窗口的大小
sigmaX: X轴方向的卷积核标准差
sigmaY: Y轴方向的卷积核标准差,默认为零表示X=Y,当sigmaX,sigmaY同时为零的时候会从ksize中进行推算出sigmaX,sigmaY,
borderType: 边界处理方式
例子:利用你高斯模糊处理图片
void Demo::Gaussian_Blur(Mat &src){
Mat dst;
GaussianBlur(src, dst, Size(17, 17), 3);
imshow("高斯模糊", dst);
GaussianBlur(src, dst, Size(17, 17), 13);
//ksize或sigmaX,sigmaY越大模糊程度越大
imshow("高斯模糊1", dst);
}
void bilateralFilter( InputArray src, OutputArray dst, int d,
double sigmaColor, double sigmaSpace,
int borderType = BORDER_DEFAULT );
返回值:空
src:输入的原图像
dst:结果图像
d: 模糊的窗口的大小,如果为零 则从sigmaSpace中计算得出
sigmaColor:颜色控件的卷积核标准差
sigmaSpace:xy空间上面的卷积和标准差,当d>0不考虑sigmaSpace的大小
borderType :边界处理的模式
例子: 利用双边模糊对任务进行美颜
void Demo::mybilateralFilter(Mat &src){
Mat dst;
//双边模糊
bilateralFilter(src,dst,0,100,10);
imshow("高斯双边模糊1", dst);
}
相对于高斯模糊和均值模糊双边模糊有一个更大的优点,就是他能够保留图片中的边界 而不会把边界进行模糊从而达到美颜的效果
void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT );
返回值: 空
src:输入的圆图像
dst: 输出的结果图像
ksize: 卷积核的大小
anchor:卷积核的锚定点(中心点)
borderType: 边界处理模式
例子 对图像进行模糊
Mat dst;
blur(src, dst, Size(9, 9));
imshow("卷积模糊", dst);
borderType | 意思 |
---|---|
BORDER_CONSTANT | |
持续更新中....请各位大佬多多指点