OpenCV小白學習筆記(三)圖像處理

圖像處理(三)

Mat對象

**1.Mat對象與IplImage對象
2.Mat對象使用
3.Mat定義數組**

Mat對象OpenCV2.0之後引進的圖像數據結構、自動分配內存、不存在內存泄漏的問題,是面向對象的數據結構。分了兩個部分,頭部與數據部分
IplImage是從2001年OpenCV發佈之後就一直存在,是C語言風格的數據結構,需要開發者自己分配與管理內存,對大的程序使用它容易導致內存泄漏問題

Mat對象常用構造函數

1.Mat()
創建一個Mat對象,在構造時不進行任何操作

//創建一個Mat對象
Mat img;

2.Mat(int rows , int cols,int type)
根據用戶指定的行數、列數以及類型創建一個Mat對象

//創建一個3*3的圖像,每個通道8個字節長度 uchar類型,通道數量爲1的Mat對象
Mat img= Mat(3,3,CV_8UC1);

3.Mat(Size size , int type)
根據用戶指定的大小以及類型,創建一個Mat對象

//讀取本地圖像返回給Mat對象src,根據src的大小,創建一個3*3的圖像,每個通道8個字節長度 uchar類型,通道數量爲1的Mat對象
Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
Mat img= Mat(src.size(),CV_8UC1);

4.Mat(int rows , int cols,int type,const Scalar &s)
根據用戶指定的行數、列數以及類型創建一個Mat對象並初始化每個像素的值,向量長度必須對應通道數

//創建一個3*3的圖像,每個通道8個字節長度 uchar類型,通道數量爲3的Mat對象,並將初始顏色設爲(127,0,255)
Mat img= Mat(3,3,CV_8UC3,Scalar(127,0,255))

5.Mat(Size size , int type , const Scalar &s)
根據用戶指定的大小以及類型,創建一個Mat對象並初始化每個像素的值,向量長度必須對應通道數

//讀取本地圖像返回給Mat對象src,根據src的大小,創建一個3*3的圖像,每個通道8個字節長度 uchar類型,通道數量爲3的Mat對象,並將初始顏色設爲(127,0,255)
Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
Mat img= Mat(src.size(),CV_8UC3,Scalar(127,0,255));

6.數組構造
使用矩陣數據構造一個Mat對象

//構成3*3
// 0  -1  0
// -1  5  -1
//  0  -1  0
//的Mat圖像
Mat mat = (Mat_<double>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);

Mat對象常用方法

1.void copyTo(Mat mat)
Mat對象深拷貝

//將src對象的圖像複製到dst對象中
Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
Mat dst;
src.copyTo(dst);

2.void converto(Mat dst,int type)
Mat對象轉化函數

//將src轉化成每個通道8個字節長度 uchar類型,通道數量爲3的Mat對象(可以在函數後面附加因子進行計算)
Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
Mat dst;
str.converto(dst,CV_8UC3);

3.Mat clone()
Mat對象深拷貝

//將src對象的圖像複製到dst對象中
Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
Mat dst;
dst.clone(src);

4.int channels()
獲取當前圖像的通道數

//獲取src的通道數
Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
int channel = src.channels();

5.int depth()
獲取當前圖像的深度

//獲取src的深度
Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
int channel = src.depth();

6.bool empty()
判斷圖像是否爲空

Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
Mat dst;
src.empty(); //false
dst.empty(); //true

7.uchar* ptr(i = 0)
獲取當前圖像的指針

//獲取src圖像的第一行對應指針
Mat src = imread("E:/OpenCV/OpenCVPicture/horse.png");
const unchar* fisrtRow = src.ptr(0);

8.Mat zeros(int rows,int cols,int type)
創建全0的Mat對象

//創建2*2每個通道8個字節長度 uchar類型,通道數量爲1的全0 Mat對象
Mat img = Mat::zeros(2,2,CV_8UC1)

9.Mat eye(int rows,int cols,int type)
創建對角線爲1的Mat對象

//創建2*2每個通道8個字節長度 uchar類型,通道數量爲1的對象線爲1 Mat對象
//1  0
//0  1
Mat img = Mat::eye(2,2,CV_8UC1)
  1. _Tp& at(int row,int col)
    獲取圖像上一個點的像素,可對其進行獲取或者修改,灰度圖像和RGB圖像有區別

    /對於灰度圖像進行像素點的獲取以及修改/
    //打開原始圖像
    Mat src = imread(“E:/OpenCV/OpenCVPicture/horse.png”);
    Mat gray_src;
    //將RGB圖像轉化成灰度圖像
    cvtColor(src,gray_src,CV_BGR2GRAY);
    //獲取灰度圖像在 (0,0)處的像素值
    uchar test = gray_src.at(0,0);
    //修改灰度圖像在 (0,0)處的像素值
    gray_src.at(0,0) = 0

    /對於RGB圖像進行像素點的獲取以及修改/
    Mat src = imread(“E:/OpenCV/OpenCVPicture/horse.png”);
    //獲取RGB像素
    uchar blue= src.at(0,0)[0]; //藍色通道像素值
    uchar green= src.at(0,0)[1]; //綠色通道像素值
    uchar red = src.at(0,0)[2]; //紅色通道像素值
    //修改RGB像素
    src.at(0,0)[0] = 0; //修改藍色通道像素爲0
    src.at(0,0)[1] = 0; //修改綠色通道像素爲0
    src.at(0,0)[2] = 0; //修改紅色通道像素爲0

Mat對象使用-四個要點

1.輸出圖像的內存是自動分配的
2.使用OpenCV的C++接口,不需要考慮內存分配問題
3.賦值操作和拷貝構造函數只會複製頭部分
4.使用clone與copyTo兩個函數實現數據完全複製

Mat對象創建(補充)

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));

cv::Mat::create實現

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", *firstRow);

代碼案例

#include <opencv2/core/core.hpp> 
#include <opencv2/imgcodecs.hpp> 
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

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;
}

圖像操作

1.讀寫圖像
2.讀寫像素
3.修改像素值

讀寫圖像

imread 可以指定加載爲灰度或者RGB圖像
Imwrite 保存圖像文件,類型由擴展名決定

讀寫像素

1.讀一個GRAY像素點的像素值(CV_8UC1)
Scalar intensity = img.at(y, x);
或者 Scalar intensity = img.at(Point(x, y));

2.讀一個RGB像素點的像素值
Vec3f intensity = img.at(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];

修改像素值

灰度圖像
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與Vec3F

Vec3b對應三通道的順序是blue、green、red的uchar類型數據。

Vec3f對應三通道的float類型數據

把CV_8UC1轉換到CV32F1實現如下:
src.convertTo(dst, CV_32F);

代碼案例

#include <opencv2/core/core.hpp> 
#include <opencv2/imgcodecs.hpp> 
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;
int main(int argc, char** args) {
Mat image = imread("D:/test.jpg", IMREAD_COLOR);
if (image.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}

int height = image.rows;
int width = image.cols;
int channels = image.channels();
printf("height=%d width=%d channels=%d", height, width, channels);
for (int row = 0; row < height; row++) {
       for (int col = 0; col < width; col++) {
                if (channels == 3) {
                         image.at<Vec3b>(row, col)[0] = 0; // blue
                         image.at<Vec3b>(row, col)[1] = 0; // green
                }
         }
}

namedWindow("My Image", CV_WINDOW_AUTOSIZE);
imshow("My Image", image);
waitKey(0);
return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章