imread功能是加载图像文件成为一个Mat对象,其中第一个参数表示图像文件名称
第二个参数,表示加载的图像是什么类型,支持常见的三个参数值
IMREAD_UNCHANGED (<0) 表示加载原图,不做任何改变
IMREAD_GRAYSCALE ( 0)表示把原图作为灰度图像加载进来
IMREAD_COLOR (>0) 表示把原图作为RGB图像加载进来
注意:OpenCV支持JPG、PNG、TIF等常见格式图像文件加载
#include
#include
using namespace std;
using namespace cv;
int main()
{
//读取图片(使用图片的绝对路径)
Mat src = imread("C:/Users/Admin/Desktop/2.jpg",IMREAD_GRAYSCALE);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);
//不加此语句图片会一闪而过
waitKey(0);
system("path");
getchar();
return 0;
}
namedWindos功能是创建一个OpenCV窗口,它是由OpenCV自动创建与释放,你无需取销毁它。
常见用法namedWindow(“Window Title”, WINDOW_AUTOSIZE)
WINDOW_AUTOSIZE会自动根据图像大小,显示窗口大小,不能人为改变窗口大小
WINDOW_NORMAL,跟QT集成的时候会使用,允许修改窗口大小。(一般不用)
imshow根据窗口名称显示图像到指定的窗口上去,第一个参数是窗口名称,第二参数是Mat对象
cvtColor的功能是把图像从一个彩色空间转换到另外一个色彩空间,有三个参数,第一个参数表示源图像、第二参数表示色彩空间转换之后的图像、第三个参数表示源和目标色彩空间如:COLOR_BGR2HLS 、COLOR_BGR2GRAY 等
cvtColor( image, gray_image, COLOR_BGR2GRAY );
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
namedWindow("output windows", WINDOW_AUTOSIZE);//创建窗口
Mat output_image;
cvtColor(src, output_image, COLOR_BGR2GRAY);
imshow("output windows", output_image);//显示创建的窗口
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
保存图像文件到指定目录路径
只有8位、16位的PNG、JPG、Tiff文件格式而且是单通道或者三通道的BGR的图像才可以通过这种方式保存
保存PNG格式的时候可以保存透明通道的图片
可以指定压缩参数
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
namedWindow("output windows", WINDOW_AUTOSIZE);//创建窗口
Mat output_image;//创建图像对象
cvtColor(src, output_image, COLOR_BGR2HLS);//图像转变
imshow("output windows", output_image);//显示创建的窗口
imwrite("C:/Users/Admin/Desktop/3.png", output_image);//保存图像,支持PNG、JPG、Tiff文件格式
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
这一节还是看别人的博客更好https://blog.csdn.net/wangyuankl123/article/details/104726702
CV_Assert(myImage.depth() == CV_8U);
Mat.ptr(int i=0) 获取像素矩阵的指针,索引i表示第几行,从0开始计行数。
获得当前行指针const uchar* current= myImage.ptr(row );
获取当前像素点P(row, col)的像素值 p(row, col) =current[col]
像素范围处理saturate_cast
saturate_cast(-100),返回 0。
saturate_cast(288),返回255
saturate_cast(100),返回100
这个函数的功能是确保RGB值得范围在0~255之间
掩膜操作提供提高图像对比度
以下代码有指针错误,具体代码需要看别人的博客,但是除去指针问题,语法是没有问题的
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
Mat resultImage;
int nchannels = src.channels();//获取通道数
int height = src.rows;
int cols = src.cols;
int width = cols * nchannels;
for (int row = 1; row < height - 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 = resultImage.ptr<uchar>(row);
for (int col = nchannels; col < nchannels * (cols - 1); col++) {
*output = saturate_cast<uchar>(5 * current[col] - previous[col] - next[col] - current[col - nchannels] - current[col + nchannels]);
output++;
}
}
namedWindow("mask_result", WINDOW_AUTOSIZE);
imshow("mask_result", resultImage);
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
Mat对象与IplImage对象
Mat对象使用
Mat定义数组
Mat对象OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分,头部与数据部分
IplImage是从2001年OpenCV发布之后就一直存在,是C语言风格的数据结构,需要开发者自己分配与管理内存,对大的程序使用它容易导致内存泄漏问题(现在一般不用)
他人博客可供参考
https://blog.csdn.net/danwuxie/article/details/81395650
https://blog.csdn.net/wangyuankl123/article/details/104732460
常用方法:
void copyTo(Mat mat)
void convertTo(Mat dst, int type)
Mat clone()
int channels()
int depth()
bool empty();
uchar* ptr(i=0)
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(127, 0, 255);
namedWindow("output windows", WINDOW_AUTOSIZE);//创建窗口
imshow("output windows", dst);//显示创建的窗口
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
Mat dst=src.clone();//克隆
namedWindow("output windows", WINDOW_AUTOSIZE);//创建窗口
imshow("output windows", dst);//显示创建的窗口
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
Mat dst;
src.copyTo(dst);
namedWindow("output windows", WINDOW_AUTOSIZE);//创建窗口
imshow("output windows", dst);//显示创建的窗口
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
Mat dst;
//src.copyTo(dst);
cvtColor(src,dst, COLOR_BGR2GRAY);
printf("the src's channels is! : %d", src.channels());
printf("the dst's channels is! : %d",dst.channels());
namedWindow("output windows", WINDOW_AUTOSIZE);//创建窗口
imshow("output windows", dst);//显示创建的窗口
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
Mat dst;
//src.copyTo(dst);
cvtColor(src,dst, COLOR_BGR2GRAY);
printf("the src's channels is! : %d", src.channels());
printf("the dst's channels is! : %d",dst.channels());
const uchar* firstRow= src.ptr<uchar>(0);
int cols = dst.cols;
int rows = dst.rows;
printf("the src's cols is : %d", cols);
printf("the dst's rows is : %d", rows);
printf("the firstRow value is! : %d", *firstRow);
/*namedWindow("output windows", WINDOW_AUTOSIZE);//创建窗口
imshow("output windows", dst);//显示创建的窗口*/
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
部分复制:一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分
Mat A= imread(imgFilePath);
Mat B(A) // 只复制
完全复制:如果想把Mat对象的头部和数据部分一起复制,可以通过如下两个API实现
Mat F = A.clone(); 或 Mat G; A.copyTo(G);
四个要点
输出图像的内存是自动分配的
使用OpenCV的C++接口,不需要考虑内存分配问题
赋值操作和拷贝构造函数只会复制头部分
使用clone与copyTo两个函数实现数据完全复制
cv::Mat::Mat构造函数
Mat M(2,2,CV_8UC3, Scalar(0,0,255))
其中前两个参数分别表示行(row)跟列(column)、第三个CV_8UC3中的8表示每个通道占8位、U表示无符号、C表示Char类型、3表示通道数目是3,第四个参数是向量表示初始化每个像素值是多少,向量长度对应通道数目一致
创建多维数组cv::Mat::create
int sz[3] = {2,2,2};
Mat L(3,sz, CV_8UC1, Scalar::all(0));
#include
#include
#include
#include
using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat image = imread("D:/test.jpg", IMREAD_GRAYSCALE);
if (image.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
namedWindow("My Image", CV_WINDOW_AUTOSIZE);
imshow("My Image", image);
Mat M;
M.create(4, 3, CV_8UC2);
M = Scalar(127,127);
cout << "M = " << endl << " " << M << endl << endl;
uchar* firstRow = M.ptr<uchar>(0);
printf("%d\n", *firstRow);
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "C = " << endl << " " << C << endl << endl;
waitKey(0);
return 0;
}
Mat C = (Mat_(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "C = " << endl << " " << C << endl << endl;
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/2.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
// imshow("ImputImage", src);//显示默认窗口
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "C = " << endl << " " << C << endl << endl;
// imshow("ImputImage", M);
/*namedWindow("output windows", WINDOW_AUTOSIZE);//创建窗口
imshow("output windows", dst);//显示创建的窗口*/
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
读写图像
读写像素
修改像素值
imread 可以指定加载为灰度或者RGB图像
Imwrite 保存图像文件,类型由扩展名决定
读一个GRAY像素点的像素值(CV_8UC1)
Scalar intensity = img.at(y, x);
或者 Scalar intensity = img.at(Point(x, y));
读一个RGB像素点的像素值
Vec3f intensity = img.at(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/3.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
//单通道图像操作
Mat grayImg;
Mat gray2;
cvtColor(src, grayImg, COLOR_BGR2GRAY);
gray2 = Mat(grayImg.size(), grayImg.type());
int height = grayImg.rows;
int width = grayImg.cols;
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
int gray = grayImg.at<uchar>(row, col);
gray2.at<uchar>(row, col) = 255 - gray;
// printf("%d",gray);
}
}
namedWindow("grayImgm", WINDOW_AUTOSIZE);
imshow("grayImgm", grayImg);
namedWindow("gray2m", WINDOW_AUTOSIZE);
imshow("gray2m", gray2);
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/Admin/Desktop/3.jpg"); //读取图片(使用图片的绝对路径)
CV_Assert(src.depth() == CV_8U);
if (src.empty()) {
printf("could not find the image!\n");
return -1;
}
imshow("ImputImage", src);//显示默认窗口
Mat dst;
dst.create(src.size(), src.type());
int height = src.rows;
int 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 = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = 255 - gray;
}
else{
int b = src.at<Vec3f>(row, col)[0];
int g = src.at<Vec3f>(row, col)[1];
int r = src.at<Vec3f>(row, col)[2];
dst.at<Vec3f>(row, col)[0] = 255 - b;
dst.at<Vec3f>(row, col)[1] = 255 - g;
dst.at<Vec3f>(row, col)[2] = 255 - r;
}
}
}
namedWindow("gray2m", WINDOW_AUTOSIZE);
imshow("gray2m", dst);
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
灰度图像
img.at(y, x) = 128;
RGB三通道图像
img.at(y,x)[0]=128; // blue
img.at(y,x)[1]=128; // green
img.at(y,x)[2]=128; // red
空白图像赋值
img = Scalar(0);
ROI选择
Rect r(10, 10, 100, 100);
Mat smallImg = img®;
Vec3b对应三通道的顺序是blue、green、red的uchar类型数据。
Vec3f对应三通道的float类型数据
把CV_8UC1转换到CV32F1实现如下:
src.convertTo(dst, CV_32F);
理论-线性混合操作
相关API (addWeighted)
g(x)=(1-α)f0(x)+αf1(x)
其中α的取值范围为0~1之间
参数1:输入图像Mat – src1
参数2:输入图像src1的alpha值
参数3:输入图像Mat – src2
参数4:输入图像src2的alpha值
参数5:gamma值//校验值,防止图片太暗
参数6:输出混合图像
saturate:用来确认取值合法
注意点:两张图像的大小和类型必须一致才可以
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src1 = imread("C:/Users/Admin/Desktop/1.jpg"); //读取图片(使用图片的绝对路径)
Mat src2 = imread("C:/Users/Admin/Desktop/2.jpg");
Mat dst;
dst.create(src1.size(), src1.type());
//CV_Assert(src.depth() == CV_8U);
if (src1.empty()|| src2.empty()) {
printf("could not find the image!\n");
return -1;
}
double alpha = 0.5;
if (src1.rows == src2.rows&&src1.cols == src1.cols&&src1.type() == src2.type()) {
addWeighted(src1, alpha,src2,(1.0-alpha),0.0,dst);
//add(src1, src2, dst, Mat());
//multiply(src1, src2, dst, 1.0);
imshow("ImputImage", src1);//显示默认窗口
namedWindow("gray2", WINDOW_AUTOSIZE);
imshow("gray2", src2);
namedWindow("gray2m", WINDOW_AUTOSIZE);
imshow("gray2m", dst);
}
else {
printf("could not do it!\n");
return -1;
}
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}
图像变换可以看作如下:
Mat new_image = Mat::zeros( image.size(), image.type() ); 创建一张跟原图像大小和类型一致的空白图像、像素值初始化为0
saturate_cast(value)确保值大小范围为0~255之间
Mat.at(y,x)[index]=value 给每个像素点每个通道赋值
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src1 = imread("C:/Users/Admin/Desktop/1.jpg"); //读取图片(使用图片的绝对路径)
Mat src2 = imread("C:/Users/Admin/Desktop/2.jpg");
Mat dst;
if (src1.empty() || src2.empty()) {
printf("could not find the image!\n");
return -1;
}
char input_win[] = "input image";
namedWindow(input_win, WINDOW_AUTOSIZE);
imshow(input_win, src2);
int height = src2.rows;
int width = src2.cols;
int nc = src2.channels();
dst= Mat::zeros(src2.size(), src2.type());
float alpha = 1.2;
float beta = 30;
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (nc = 1) {
float t = src2.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(t*alpha + beta);
}
else{
float b = src2.at<Vec3f>(row, col)[0];
float g = src2.at<Vec3f>(row, col)[1];
float r = src2.at<Vec3f>(row, col)[2];
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha+beta);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g*alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r*alpha + beta);
}
}
}
namedWindow("output", WINDOW_AUTOSIZE);
imshow("output", dst);
waitKey(0);//不加此语句图片会一闪而过
system("path");
getchar();
return 0;
}