文章目錄
注:轉載請標明原文出處鏈接:https://xiongyiming.blog.csdn.net/article/details/106931100
1基礎知識
Mat對象 OpenCV2.0之後引進的圖像數據結構、自動分配內存、不存在內存泄漏的問題,是面向對象的數據結構。Mat對象分爲頭部 和 數據兩個部分。
IplImage 是從2001年OpenCV發佈之後就一直存在,是C語言風格的數據結構,需要開發者自己分配與管理內存,對大的程序使用它容易導致內存泄漏問題。IplImage從本質上講,它是Mat對象,但它還有其他一些成員變量將矩陣解釋爲圖像。
Mat對象構造函數有:
Mat();
Mat(int rows, int cols, int type);
Mat(Size size, int type)
Mat(int rows, int cols, int type, const Scalar $s);
Mat(int ndims, const int *sizes, int type);
Mat(int ndims, const int *sizes, int type, const Scalar &s);
Mat對象常用的函數有:
void copyTo(Mat mat);
void convertTo(Mat dst, int type);
Mat clone();
int channels();
int depth();
bool empty();
uchar* ptr(i=0);
Mat對象使用的注意事項
(1) 部分複製:一般情況下只會複製Mat對象的頭部和指針部分,不會複製數據部分
Mat A= imread(imgFilePath);
Mat B(A) // 只複製
(2) 完全複製:如果把Mat對象的頭部和數據部分一起復制,可以通過如下兩個代碼
實現
Mat F = A.clone();
或
Mat G;
A.copyTo(G);
Mat對象使用的四個要點
- 輸出圖像的內存是自動分配的;
- 使用OpenCV的C++接口,不需要考慮內存分配問題;
- 賦值操作和拷貝構造函數只會複製頭部分;
- 使用clone與copyTo兩個函數實現數據完全複製;
2 代碼示例
2.1 創建一張空白圖像
代碼
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat src = imread("ZXP1.jpg", IMREAD_UNCHANGED);
if (src.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", src);
Mat dst;
dst = Mat(src.size(), src.type()); //或者用 dst.create(src.size(), src.type());
dst = Scalar(255, 255, 255);
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
waitKey(0);
return 0;
}
運行結果
2.2 clone
代碼
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat src = imread("ZXP1.jpg", IMREAD_UNCHANGED);
if (src.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", src);
/*
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(255, 255, 255);
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
*/
Mat dst = src.clone();
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
waitKey(0);
return 0;
}
運行結果
2.3 cvtcolor
代碼
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat src = imread("ZXP1.jpg", IMREAD_UNCHANGED);
if (src.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", src);
/*
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(255, 255, 255);
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
*/
Mat dst;
src.copyTo(dst);
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
waitKey(0);
return 0;
}
運行結果
2.4 channels
代碼
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat src = imread("ZXP1.jpg", IMREAD_UNCHANGED);
if (src.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", src);
/*
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(255, 255, 255);
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
*/
Mat dst;
cvtColor(src, dst, CV_BGR2GRAY);
printf("原始圖像的通道數爲:%d\n", src.channels());
printf("輸出圖像的通道數爲:%d\n", dst.channels());
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
waitKey(0);
return 0;
}
運行結果
2.5 cols、rows 和 uchar* ptr
代碼
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat src = imread("ZXP1.jpg", IMREAD_UNCHANGED);
if (src.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", src);
/*
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(255, 255, 255);
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
*/
Mat dst;
cvtColor(src, dst, CV_BGR2GRAY);
printf("原始圖像的通道數爲:%d\n", src.channels());
printf("輸出圖像的通道數爲:%d\n", dst.channels());
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
int rows = dst.rows;
int cols = dst.cols;
printf("rows = %d , cols = %d\n", rows, cols);
const uchar* firstRow = dst.ptr<uchar>(0);
printf("first pixel value = %d\n", *firstRow);
waitKey(0);
return 0;
}
運行結果
2.6 構建一個窗口
代碼
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat src = imread("ZXP1.jpg", IMREAD_UNCHANGED);
if (src.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", src);
/*
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(255, 255, 255);
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
*/
Mat dst;
cvtColor(src, dst, CV_BGR2GRAY);
printf("原始圖像的通道數爲:%d\n", src.channels());
printf("輸出圖像的通道數爲:%d\n", dst.channels());
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
int rows = dst.rows;
int cols = dst.cols;
printf("rows = %d , cols = %d\n", rows, cols);
const uchar* firstRow = dst.ptr<uchar>(0);
printf("first pixel value = %d\n", *firstRow);
Mat M1(3, 3, CV_8UC3, Scalar(255, 255, 255));
cout << "M1=" << endl << M1 << endl;
waitKey(0);
return 0;
}
運行結果
注意
- 對於int類型8位,CvMat矩陣對應的參數類型爲
CV_8UC1
、CV_8UC2
、CV_8UC3
(其中,數字1、2、3表示通道數,比如 RGB 圖像有3通道,就用CV_8UC3
,灰度圖像就用CV_8UC1
) - 對於float類型32位,對應CvMat數據結構參數爲:
CV_32FC1
、CV_32FC2
、CV_32FC3
等; - 對於double 類型64位,對應CvMat數據結構參數爲:
CV_64FC1
、CV_64FC2
、CV_64FC3
等。
2.7 zeros
代碼
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat src = imread("ZXP1.jpg", IMREAD_UNCHANGED);
if (src.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", src);
/*
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(255, 255, 255);
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
*/
Mat dst;
cvtColor(src, dst, CV_BGR2GRAY);
printf("原始圖像的通道數爲:%d\n", src.channels());
printf("輸出圖像的通道數爲:%d\n", dst.channels());
namedWindow("Output Image", CV_WINDOW_AUTOSIZE);
imshow("Output Image", dst);
Mat M2 = Mat::zeros(3, 3, CV_8UC1);
cout << "M2=" << endl << M2 << endl;
waitKey(0);
return 0;
}
運行結果
參考資料
[1] https://edu.51cto.com/course/7521.html?source=so