https://download.csdn.net/download/qq_38649386/13986488
目录
1 图像采集 1
1.1 数据类型 1
1.1.1 Mat 1
1.2 图像加载、截取、转色域 3
1.2.1 格式与信息 3
1.2.2 imread 3
1.2.3 Rect 4
1.2.4 cvtColor 5
1.3 加载视频 6
1.3.1 VideoCapture 1 读摄像头 6
1.3.2 VideoCapture 2 拍照保存 6
1.3.3 VideoCapture 3 保存视频 7
1.3.4 VideoCapture 4 读取视频 8
1.4 图像掩膜 9
1.4.1 像素指针 9
1.4.2 像素范围处理 9
1.4.3 filter2D & src.ptr<>() 9
1.4.4 src.at<>() 11
2 几何变换 14
2.1 形状变换 14
2.1.1 图像缩放 14
2.1.2 resize 14
2.1.3 pyramid特征金字塔 16
2.1.4 DOG 高斯不同 17
2.1.2 图像错切 18
2.2 位置变换 19
2.2.1 平移变换 19
2.2.2 镜像变换 19
2.2.3 旋转变换 20
2.2.4 warpAffine 20
2.3 仿射变换 22
2.4 基本运算 22
2.4.1 点运算 22
2.4.2 point process像素访问 23
2.4.3 代数运算 25
2.4.4 addWeighted 25
2.4.5 逻辑运算 26
2.4.6 &|~ 27
2.4.7 split 29
2.4.8 plant画图形 30
3 图像增强 33
3.1 对比度线性展宽 33
3.1.1 change contrast 33
3.2 非线性动态范围调整 34
3.3 直方图均衡化 35
3.4 伪彩色增强 35
3.4.1 密度分层法 35
3.4.2 空域灰度级彩色变换法 36
3.4.3 频域伪彩色增强法 36
3.4.4 applyColorMap 36
3.4.5 LUT 36
4 图像去噪 38
4.1 常见噪声模型与滤波模型 38
4.1.1 addSaltNoise 38
4.2 主要滤波函数 39
4.2.1 均值滤波 39
4.2.2 中值滤波 39
4.2.3 高斯滤波 39
4.2.4 双边滤波 40
4.3 filter API 40
4.3.1 filter 1 40
4.3.2 filter 2 41
4.3.3 filter 3 42
4.3.4 filter 4 43
4.4 其他滤波方法 44
5 边缘提取 45
5.1 Robert算子 45
5.1.1 All Filter Function 45
5.2 Sobel算子 47
5.2.1 example code 1 48
5.2.2 sobel&scharr提取边界 48
5.3 Priwitt算子 51
5.3 Laplance算子 51
5.3.1 example code 1 52
5.3.2 example code 2 52
5.3.3 example code 3 53
5.4 Canny算子 54
5.4.1 example code 1 54
5.4.2 example code 2 55
5.5 边缘处理 57
5.5.1 copyMakeBorder 57
5.5.2 自适应阈值分割 58
6 图像形态学 60
6.1 膨胀 60
6.2 腐蚀 60
6.2.1 dilate&erode 1 60
6.2.2 dilate&erode 2 61
6.3 开运算 63
6.4 闭运算 63
6.4.1 open&close 1 64
6.5 形态学梯度 64
6.6 顶帽运算 65
6.7 黑帽运算 65
6.7.1 open&close&top&black 65
6.8 提取水平和垂直线 67
6.8.1 example code 67
Mat(nrow
,ncols
,type
[,fillValue]
)
数据类型:
U usigned char(无符号字符型,不是无符号整型)
C 通道数
S signed int(有符号整型)
CV_8U 0~255
CV_8S 0~255
CV_32S int型的范围
CV_32F 浮点型的范围
填充的数值(矩阵fillvalue):
Scalar(0, 0, 255) 红色,自动填充三通道颜色
Scalar(100) 灰度图颜色填充
Size(240,250) 创建Mat大小
/**********************************
@函数名称:create_image
@函数输入:
@函数输出:
@函数功能:用Mat创建图片
,自定义格式
,颜色
**********************************/
void create_image() {
// cv::Mat img(240, 240, CV_8UC3, cv::Scalar(0, 0, 255));
cv::Mat img(cv::Size(240, 500), CV_8UC3, cv::Scalar(0, 0, 255));
cv::imshow("test", img);
cv::waitKey(0);
cv::destroyAllWindows();
}
/**********************************
@函数名称:Mat_image
@函数输入:none
@函数输出:none
@函数功能:图像Mat操作
**********************************/
void Mat_image(void) {
/* 原图像 */
cv::Mat src = cv::imread("./img/shi.png", cv::IMREAD_COLOR);
if (!src.data) { // src.empty()
std::cerr << "error input" << std::endl;
return;
}
cv::namedWindow("srcImage", CV_WINDOW_AUTOSIZE);
cv::imshow("srcImage", src);
/* method Mat */
cv::Mat dst1;
dst1 = cv::Mat(src.size(), src.type(), cv::Scalar(0,0,255)); // 自定义初始化数据
// dst1 = cv::Scalar(0,0,255);
cv::namedWindow("dst1Image", CV_WINDOW_AUTOSIZE);
cv::imshow("dst1Image", dst1);
cv::Mat M(5, 5, CV_8UC3, cv::Scalar(127));
std::cout << "M =" << std::endl << M << std::endl;
/* method copyTo */
cv::Mat dst2;
src.copyTo(dst2); // API
cv::namedWindow("dst2Image", CV_WINDOW_AUTOSIZE);
cv::imshow("dst2Image", dst2);
/* method clone */
cv::Mat dst3 = src.clone(); // 完全数据拷贝
cv::namedWindow("dst3Image", CV_WINDOW_AUTOSIZE);
cv::imshow("dst3Image", dst3);
/* method create */
cv::Mat dst4;
dst4.create(src.size(), src.type());
dst4 = cv::Scalar(0, 255, 255);
cv::namedWindow("dst4Image", CV_WINDOW_AUTOSIZE);
cv::imshow("dst4Image", dst4);
/* 图像指针 */
cv::Mat graydst;
cv::cvtColor(src, graydst, cv::COLOR_BGR2GRAY);
const uchar* firstRow = graydst.ptr<uchar>(0);
// std::cout << "gray image's first point is: " << *firstRow << std::endl; //没有结果
printf("fist pixel value : %d\n", *firstRow);
/* 尺寸 */
int row = graydst.rows;
int col = graydst.cols;
int channel = graydst.channels();
std::cout << "The image's size is: " << row << " * " << col << " * " << channel << std::endl;
cv::waitKey(0);
cv::destroyAllWindows();
}
flags包括:
IMREAD_GRAYSCALE 灰色
IMREAD_COLOR 彩色
image information:
image.empty() 判断是否为空,空位true
image.cols 列数
image.rows 行数
image.channels() 通道数
imread(filename
,int flags=IMREAD_COLOR
)
/**********************************
@函数名称:read_image
@函数输入:图片目录地址
@函数输出:显示图片窗口
@函数功能:读取图片
**********************************/
void read_image() {
std::string img_addr = "./img/shi.jpg"; // 设置读取目录地址
/* 输入读取图像方式 */
cv::Mat image = cv::imread(img_addr); // 读取图片
// cv::Mat image = cv::imread(img_addr, cv::IMREAD_GRAYSCALE); // 灰色图像-CV_8U
// cv::Mat image = cv::imread(img_addr, cv::IMREAD_COLOR); // 彩色图像-CV_8UC3
if (image.empty()) { // 错误处理
std::cout << "input image error!!!" << std::endl;
return;
}
/* 显示加载图片基本信息*/
std::cout << "This image size is " << image.rows << " * " << image.cols << std::endl;
std::cout << "This image channal has " << image.channels() << "channels" << std::endl;
cv::namedWindow("InputImage"); // 创建窗口
cv::imshow("InputImage", image); // 显示图片
cv::waitKey(0); // 等待按键输入
cv::destroyAllWindows(); // 关闭所有窗口
}
region of interest。ROI-感兴趣区域。Rect Rect(int x, int y, int width, ind height)
// 列,行,加列,加行
/**********************************
@函数名称:ROI-》Rect函数
@函数输入:
@函数输出:
@函数功能:选取感兴趣区域,并叠加
**********************************/
void ROI_image(void) {
/* 加载图片2 */
cv::Mat img2 = cv::imread("./img/shi.png");
cv::namedWindow("image2");
cv::imshow("image2", img2);
std::cout << "image 1:" << img2.rows << " * " << img2.cols << std::endl;
cv::Mat imageROI = img2(cv::Rect(170, 10, 100, 120));
// 列, 行,加列,加行
cv::namedWindow("ROIimage");
cv::imshow("ROIimage", imageROI);
cv::waitKey(0);
cv::destroyAllWindows();
}
void cv::cvtColor (InputArray src,
OutputArray dst,
int code,
int dstCn = 0
)
/**********************************
@函数名称:cvtcolor_image
@函数输入:none
@函数输出:none
@函数功能:转色域
**********************************/
void read_image_V(void) {
/* 原图像 */
cv::Mat src = cv::imread("./img/shi.png", cv::IMREAD_COLOR);
if (!src.data) { // src.empty()
std::cerr << "error input" << std::endl;
return;
}
/* 转色域 */
cv::Mat dst;
cv::cvtColor(src, dst,cv::COLOR_BGR2GRAY);
cv::namedWindow("srcImage", CV_WINDOW_NORMAL);
cv::namedWindow("dstImage", CV_WINDOW_AUTOSIZE);
cv::imshow("srcImage", src);
cv::imshow("dstImage", dst);
cv::waitKey(0);
cv::destroyAllWindows();
}
保存格式:(opencv版本不一样,宏定义不一样)
cv::CAP_OPENCV_MJPEG MP4
/**********************************
@函数名称:read_camera
@函数输入:
@函数输出:
@函数功能:调用摄像头
**********************************/
void read_camera(void) {
cv::VideoCapture myCapture(0); // 摄像头型号
cv::namedWindow("ShowCamera", cv::WINDOW_NORMAL); // 窗口设置,可手动调整
while (1) {
cv::Mat myFrame;
myCapture >> myFrame;
if (myFrame.empty()) {
break;
}
cv::imshow("ShowCamera", myFrame);
cv::waitKey(10);
}
}
/**********************************
@函数名称:take_pictures
@函数输入:可修改调用摄像头序号
可修改图片保存目录地址
@函数输出:
@函数功能:调用摄像头,按space拍照
按ESC退出
**********************************/
void take_pictures() {
cv::VideoCapture mycapture(0);
std::string writePath = "./img/";
std::string name;
cv::Mat frame;
int i = 0;
while (true){
mycapture >> frame; // 从视频序列中取出一张图片数据,存储到frame
//if (!mycapture.isOpened()) // 有360摄像头保护容易出错
// std::cout << "error" << std::endl;
// break;
if (frame.empty()) // 输入保护
break;
if (cv::waitKey(1) == 32) { // space拍照保存
std::cout << "saving picture" << std::endl;
//name = writePath + char(i) + ".jpg";
name = writePath + char('0'+i) + ".jpg";
cv::imwrite(name, frame);
std::cout << name << std::endl;
i++;
}
cv::imshow("readCamera", frame);
if (cv::waitKey(100) == 27) // ESC退出
break; // 1-10效果不好,100还行,稍有卡顿
}
}
/**********************************
@函数名称:write_video
@函数输入:
@函数输出:
@函数功能:保存摄像头视频,按ESC退出
**********************************/
void write_video() {
cv::VideoCapture myCapture(0); // 初始化摄像头
cv::VideoWriter myVideoWritter; // 生成视频实例化
myVideoWritter.open(
"./img/Video1.mp4" // avi 不行
, cv::CAP_OPENCV_MJPEG // 和格式有关
, 30.0
, cv::Size(640, 480)
, true
);
cv::namedWindow("show", cv::WINDOW_NORMAL);
int i = 0;
while (i < 100) {
i++;
cv::Mat myFrame;
myCapture >> myFrame;
if (myFrame.empty()) {
break;
}
cv::imshow("show", myFrame);
//myVideoWriter << myFrame;
myVideoWritter.write(myFrame);
cv::waitKey(30);
}
myCapture.release();
myVideoWritter.release();
}
/**********************************
@函数名称:read_video
@函数输入:
@函数输出:
@函数功能:读取视频
**********************************/
void read_video(void) {
cv::VideoCapture myCapture("./img/Video1.mp4"); // 摄像头型号
cv::namedWindow("ShowCamera", cv::WINDOW_NORMAL); // 窗口设置,可手动调整
while (1) {
cv::Mat myFrame;
myCapture >> myFrame;
if (myFrame.empty()) {
break;
}
cv::imshow("ShowCamera", myFrame);
cv::waitKey(10);
}
}
Mat.ptr
// 获取像素矩阵的指针,索引i表示第几行,从0开始计行数。
const uchar* current= myImage.ptr
// 获得当前行指针
像素范围处理saturate_cast
saturate_cast
saturate_cast
saturate_cast
这个函数的功能是确保RGB值得范围在0~255之间
void cv::filter2D (InputArray src,
OutputArray dst,
int ddepth,
InputArray kernel,
Point anchor = Point(-1,-1),
double delta = 0,
int borderType = BORDER_DEFAULT
)
/**********************************
@函数名称:ptr_image
@函数输入:none
@函数输出:none
@函数功能:图像像素操作
**********************************/
void ptr_image(void) {
cv::Mat src, dst_ptr, dst_API;
/* 加载原图像 */
src = cv::imread("./img/shiyuan.png", cv::IMREAD_COLOR);
if (!src.data) { // src.empty()
std::cerr << "could not load image..." << std::endl;
return;
}
/* 指针像素点处理 */
int rows = src.rows; // 行
int cols = (src.cols - 1) * src.channels(); // 真实列数为列数*通道数,并且需要减一
int offsetx = src.channels(); // 通道
dst_ptr = cv::Mat::zeros(src.size(), src.type()); // 初始化dst
// 两个需要时函数,变量报错
/* 定义耗费时间 */
double time, timeCost;
time = cv::getTickCount();
/* 遍历行 */
for (int row = 1; row < rows - 1; row++) { // 留出第一行,留出最后一行,自行处理
/* 初始化指针变量 */
const uchar* previous = src.ptr<uchar>(row - 1); // 指向前一行
const uchar* current = src.ptr<uchar>(row); // 指向当前行
const uchar* next = src.ptr<uchar>(row + 1); // 指向后一行
uchar* output = dst_ptr.ptr<uchar>(row); // output已经指向当前行
/* 遍历列 */
for (int col = offsetx; col < cols; col++) { // 在行一定的条件下,遍历列
output[col]=cv::saturate_cast<uchar>( // output在当前行中,计算各个列的值
5 * current[col] - (current[col - offsetx]
+ current[col + offsetx]
+ previous[col] + next[col]
)
);
}
}
timeCost = (cv::getTickCount() - time) / cv::getTickFrequency();
std::cout << "ptr method cost time: " << timeCost << std::endl;
/* API-filter2D像素处理 */
time = cv::getTickCount();
cv::Mat kernel = (cv::Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); // 是char,不是uchar
cv::filter2D(src, dst_API, src.depth(), kernel); // -1
timeCost = (cv::getTickCount() - time) / cv::getTickFrequency();
std::cout << "API method time cost: " << timeCost << std::endl;
/* 创建窗口 */
cv::namedWindow("srcImage", CV_WINDOW_AUTOSIZE);
cv::namedWindow("dstImage_ptr", CV_WINDOW_AUTOSIZE);
cv::namedWindow("dstImage_API", CV_WINDOW_AUTOSIZE);
/* 显示图片 */
cv::imshow("srcImage", src);
cv::imshow("dstImage_ptr", dst_ptr);
cv::imshow("dstImage_API", dst_ptr);
/* 销毁窗口 */
cv::waitKey(0);
cv::destroyAllWindows();
}
/**********************************
@函数名称:point_image
@函数输入:none
@函数输出:none
@函数功能:图像负片效果操作
**********************************/
void point_image(void) {
/* 加载原图像 */
cv::Mat src;
src = cv::imread("./img/shiyuan.png");
if (!src.data) {
std::cerr << "Could not load image" << std::endl;
return;
}
cv::namedWindow("srcImage", CV_WINDOW_AUTOSIZE);
cv::imshow("srcImage", src);
/* 转灰色图像 */
cv::Mat gray_src;
cv::cvtColor(src, gray_src, CV_BGR2GRAY);
cv::namedWindow("grayImage", CV_WINDOW_AUTOSIZE);
cv::imshow("grayImage", gray_src);
/* 单通道处理 */
/* 函数操作像素,非指针操作 */
cv::Mat gray_dst;
gray_dst.create(gray_src.size(), gray_src.type()); // 必须要初始化
int height = gray_src.rows;
int width = gray_src.cols;
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
int gray = gray_src.at<char>(row, col); // 类函数操作像素
gray_dst.at<uchar>(row, col) = 255 - gray; // 底片效果
}
}
cv::namedWindow("grayImage_at", CV_WINDOW_AUTOSIZE);
cv::imshow("grayImage_at", gray_dst);
/* 多通道处理 */
cv::Mat dst;
dst.create(src.size(), src.type());
// dst = cv::Scalar(255, 0, 0); // 初始化颜色-蓝色
height = src.rows;
width = src.cols;
int nc = src.channels();
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (nc == 1) {
int gray = gray_src.at<char>(row, col); // 用的灰色原图数据
dst.at<uchar>(row, col) = 255 - gray;
}
else if(nc==3){
int b = src.at
int g = src.at
int r = src.at
dst.at
dst.at
dst.at
}
}
}
cv::namedWindow("Image_channels", CV_WINDOW_AUTOSIZE);
cv::imshow("Image_channels", dst);
/* bitwise_not API */
cv::Mat dst_bitwise;
cv::bitwise_not(src, dst_bitwise);
cv::namedWindow("Image_bitwise", CV_WINDOW_AUTOSIZE);
cv::imshow("Image_bitwise", dst_bitwise);
/* 取最值的方法处理成灰色图 */
cv::Mat dst_maxmin;
dst_maxmin.create(src.size(), src.type());
height = src.rows;
width = src.cols;
nc = src.channels();
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (nc == 1) {
int gray = gray_src.at<char>(row, col);
dst_maxmin.at<uchar>(row, col) = 255 - gray;
}
else if (nc == 3) {
int b = src.at
int g = src.at
int r = src.at
gray_dst.at<uchar>(row, col) = min(r, min(g, b)); // max & min
}
}
}
cv::namedWindow("Image_maxmin", CV_WINDOW_AUTOSIZE);
cv::imshow("Image_maxmin", gray_dst);
cv::waitKey(0);
cv::destroyAllWindows();
}
Geometric Operation
即:
fx,fy为缩放比例。
Resizes an image。
C++:
void resize(InputArray src
, OutputArray dst
, Size dsize
, double fx=0
, double fy=0
, int interpolation=INTER_LINEAR
)
Python:
cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) → dst
Parameters:
插值方法:
INTER_NEAREST-最近邻插值
INTER_LINEAR-双线性插值(默认情况下使用)
区域间-使用像素-面积关系重新采样。这可能是图像抽取的首选方法,因为它可以得到无云纹的结果。但当图像被放大时,它类似于最近邻法。
INTER_CUBIC-4x4像素邻域上的双三次插值
INTER_LANCZOS4-8x8像素邻域上的Lanczos插值
/**********************************
@函数名称:interpolation
@函数输入:
@函数输出:
@函数功能:resize
**********************************/
void interpolation(void) {
cv::Mat srcImage = cv::imread("./img/shi.png");
cv::Mat dstImage;
cv::imshow("srcShow", srcImage);
cv::resize(srcImage, dstImage, cv::Size(256, 256), 0, 0, cv::INTER_LINEAR);
cv::imshow("desShow", dstImage);
cv::waitKey(0);
}
pyrUp:
Upsamples an image and then blurs it.
C++:
void pyrUp(InputArray src
, OutputArray dst
, const Size& dstsize=Size()
, int borderType=BORDER_DEFAULT
)
Python:
cv2.pyrUp(src[, dst[, dstsize[, borderType]]]) → dst
C:
cvPyrUp(const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 )
pyrDown:
Blurs an image and downsamples it.
C++:
void pyrDown(InputArray src
, OutputArray dst
, const Size& dstsize=Size()
, int borderType=BORDER_DEFAULT
)
Python:
cv2.pyrDown(src[, dst[, dstsize[, borderType]]]) → dst
C:
void cvPyrDown(const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 )
/**********************************
@函数名称:pyramid
@函数输入:
@函数输出:
@函数功能:金字塔法放缩图像
**********************************/
void pyramid(void) {
/* 原始图像 */
cv::Mat srcImage = cv::imread("./img/shi.png");
cv::Mat dstImage0, dstImage1;
cv::imshow("Source Image", srcImage);
/* 上采样 */
cv::pyrUp(srcImage, dstImage0, cv::Size(srcImage.cols * 2, srcImage.rows * 2));
cv::imshow("pyrUp Image", dstImage0);
/* 下采样 */
cv::pyrDown(srcImage, dstImage1, cv::Size(srcImage.cols / 2, srcImage.rows / 2));
cv::imshow("pyrDown Image", dstImage1);
cv::waitKey(0);
cv::destroyAllWindows();
}
/**********************************
@函数名称:pyr_up_dowm
@函数输入:none
@函数输出:none
@函数功能:采样-DOG
**********************************/
void pyr_up_down(void) {
/* 原图像 */
cv::Mat src = cv::imread("./img/shiyuan.png");
if (!src.data) {
std::cerr << "error input" << std::endl;
return;
}
cv::namedWindow("srcImage", CV_WINDOW_AUTOSIZE);
cv::imshow("srcImage", src);
/* 上采样 */
cv::Mat dst_pyrup;
cv::pyrUp(src, dst_pyrup, cv::Size(src.cols * 2, src.rows * 2)); // 先列,再行
cv::imshow("pyrup", dst_pyrup);
/* 下采样 */
cv::Mat dst_pyrdown;
cv::pyrDown(src, dst_pyrdown, cv::Size(src.cols / 2, src.rows / 2)); // 先列,再行
cv::imshow("pyrdown", dst_pyrdown);
/* DOG-高斯不同 */
cv::Mat dst_gray, g1, g2, dst_dog;
cv::cvtColor(src, dst_gray, CV_BGR2GRAY);
cv::GaussianBlur(dst_gray, g1, cv::Size(5, 5), 0, 0);
cv::GaussianBlur(g1, g2, cv::Size(3, 3), 0, 0);
cv::subtract(g1, g2, dst_dog, cv::Mat()); // 低减高
/* 归一化显示 */
cv::normalize(dst_dog, dst_dog, 255, 0, cv::NORM_MINMAX);
cv::imshow("DOG Image", dst_dog);
cv::waitKey(0);
cv::destroyAllWindows();
}
设变换矩阵T。
经过水平错切后:
c为y坐标轴与图像边界夹角c=tanα,当c<0,则沿+x方向错切,反之,c>0,则沿-x方向错切。
经过垂直错切后:
b为x坐标轴与图像边界夹角b=tanβ,当b>0,则沿+y方向错切,反之,b<0,则沿-y方向错切。
得:
1.水平镜像变换:
(M行N列)X轴坐标不变的情况下,Y轴坐的标数值变。
2.垂直镜像变换:
(M行N列)Y轴坐标不变的情况下,X轴坐标的数值变。
3.对角镜像变换:
(M行N列)Y轴坐标的数值变,X轴坐标的数值变。
旋转前:(旋转之前,直线与X轴夹角为β)
旋转后:(旋转之后,两条直线之间的夹角为α)
矩阵形式:
Applies an affine transformation to an image.
C++:
void warpAffine(InputArray src
, OutputArray dst
, InputArray M
, Size dsize
, int flags=INTER_LINEAR
, int borderMode=BORDER_CONSTANT
, const Scalar& borderValue=Scalar()
)
Python:
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
/**********************************
@函数名称:rotate_image
@函数输入:
@函数输出:
@函数功能:图像旋转
**********************************/
void rotate_image(void) {
int degree = 45; // 定义旋转角度
/* 原始图像 */
cv::Mat srcImage = cv::imread("./img/shi.png");
cv::Mat dstImage;
cv::imshow("srcImage", srcImage);
/* 旋转中心为图像中心 */
cv::Point2f center;
center.x = float(srcImage.cols / 2.0 + 0.5);
center.y = float(srcImage.rows / 2.0 + 0.5);
/* 计算二维旋转的仿射变换矩阵 */
cv::Mat M; // 仿射变换矩阵
M = cv::getRotationMatrix2D(center, degree, 0.7);
/* 变换图像,并用黑色填充 */
cv::warpAffine(srcImage, dstImage, M, dstImage.size());
cv::imshow("dstshow", dstImage);
cv::waitKey(0);
cv::destroyAllWindows();
}
,表示恒等变换
,表示平移变换
,表示缩放变换
,表示旋转变换
Point Operation-点运算也称为:对比度增强、对比度拉伸、灰度变换。
T表示灰度变换函数,g()表示输出图像灰度,f()表示输入图像灰度。
1.线性点运算:
当a>1,输出图像灰度拓展,对比度增大;