1 加载修改保存图像
1.1 修改图像
opencv中 灰度图像由常量 CV_8U 表示 C++ 中的 unsigned char;
三通道图像由 常量 CV_8UC3 表示;
1.2 保存图像
#include<stdio.h>
#include <cstdio>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image;
image = cv::imread("F:/project/OPENCV_TEST_PROJECT/picture/test.jpg");
if (image.empty()) {
cout << "error";
return 0;
}
cv::namedWindow("Original Image");
cv::imshow("Original Image",image);
Mat result;
cv::flip(image,result,1);//反转图片 正数表示水平 ;0 表示垂直;负数表示水平和垂直
cv::namedWindow("Flip Image");
cv::imshow("Flip Image", result);
cv::imwrite("F:/project/OPENCV_TEST_PROJECT/picture/flip.jpg", result);//保存结果
cv::waitKey(0);//0 表示等待按键
}
1.3 在图片上绘制形状或添加文字
#include<stdio.h>
#include <cstdio>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image;
image = cv::imread("F:/project/OPENCV_TEST_PROJECT/picture/test.jpg");
if (image.empty()) {
cout << "error";
return 0;
}
cv::namedWindow("Original Image");
cv::imshow("Original Image",image);
cv::circle(image, cv::Point(155, 110), //中心点坐标
55, //半径
0, //颜色
3);//厚度
cv::namedWindow("Result Image");
cv::imshow("Result Image", image);
cv::waitKey(0);//0 表示等待按键
}
可使用 cv::putText 函数在图片上添加文字。
1.4 定义感兴趣区域ROI
#include<stdio.h>
#include <cstdio>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image;
image = cv::imread("F:/project/OPENCV_TEST_PROJECT/picture/test.jpg");
if (image.empty()) {
cout << "error";
return 0;
}
//创建一个240*330 红色图像 通道是bgr
Mat image2(500,330,CV_8UC3,cv::Scalar(0,0,255));
//在图像的右下角定义一个感兴趣区域
Mat imageROI(image,
cv::Rect(image.cols - image2.cols, //ROI坐标
image.rows - image2.rows,
image2.cols, image2.rows)); //ROI 大小
//插入
image2.copyTo(imageROI);
cv::namedWindow("Original Image");
cv::imshow("Original Image", image);
cv::waitKey(0);//0 表示等待按键
}
显示效果如下所示,原图上增加 红色矩阵:
2 像素操作
2.1 使用指针的方式操作图像
获取一行像素值的字节数
int nc = image.cols * images.channels();
返回一行元素的起始地址
uchar * data = image.ptr<uchar>(j);//j为第j行的地址
操作像素的字节
*data = *data/8;
对原图像进行拷贝
cv::Mat iamgeClone = image.clone();//图像的深拷贝
使用迭代器遍历图像元素
cv::Mat<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>();
cv::Mat<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>();
for(;it!=itend;++it)
{
(*it)[0] = 112;//[]中访问元素通道
(*it)[1] = 255;//[]中访问元素通道
(*it)[2] = 255;//[]中访问元素通道
}
2.2 访问图像元素
生成椒盐噪声:
#include<stdio.h>
#include <cstdio>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
#include <random>
void salt(cv::Mat image, int n) { //待处理如下,生成的椒盐噪声数量
std::random_device seed_device;
std::default_random_engine engine(seed_device());//通过operator()取得设备产生的随机值
std::uniform_int_distribution<int> distrRow(0, image.rows -1);//10到100,int类型,线性分布
std::uniform_int_distribution<int> distrCols(0, image.cols - 1);//10到100,int类型,线性分布
int i, j;
for (int k = 0; k < n; k++) {
i = distrRow(engine);
j = distrCols(engine);
if (image.type() == CV_8UC1) { //灰度图
image.at<uchar>(i, j) = 255;
}
else if (image.type() == CV_8UC3) { //灰度图
image.at<cv::Vec3b>(i, j)[0] = 255;
image.at<cv::Vec3b>(i, j)[1] = 255;
image.at<cv::Vec3b>(i, j)[2] = 255;
}
}
engine.seed(); //将引擎设为初始化状态
cv::namedWindow("Original Image");
cv::imshow("Original Image", image);
}
使用Mat.at方法访问元素,at方法被实现成一个模板方法,调用时必须指定图像元素的类型。
image.at<cv::Vec3b>(i, j)[0] = 255;
2.3 计算某段代码运行的时间
const int64 start = cv::getTickCount();//获取计算机开机到当前的时钟周期数
//运行一段代码
double duration = (cv::getTickCount()-start)/cv::getTickFrequency();//换算为以秒为单位
2.4 扫描图像并访问相邻元素
滤波函数 cv::filter2D,定义内核kernel
void sharpen2D(const cv::Mat &image,cv::Mat &result)
{
cv::Mat kernel(3,3,CV_32F,cv::Scalar(0));//构造内核,所有入口初始化为0
//对内核赋值
kernel.at<float>(1,1)=5.0;
kernel.at<float>(0,1)=-1.0;
kernel.at<float>(2,1)=-1.0;
kernel.at<float>(1,0)=-1.0;
kernel.at<float>(1,2)=-1.0;
//对图像滤波操作
cv::filter2D(image,result,image.depth(),kernel);
}