OpenCV圖像操作

2018-08-29 14:05 更新

輸入/輸出

圖片

從文件加載圖像:

Mat img = imread(filename)

如果您讀取jpg文件,則默認(rèn)情況下會創(chuàng)建3通道映像。如果需要灰度圖像,請使用:

Mat img = imread(filename,IMREAD_GRAYSCALE);
注意
文件的格式由其內(nèi)容決定(前幾個字節(jié))將圖像保存到文件中:
imwrite(filename,img);
注意
文件的格式由其擴展名決定。
使用imdecode和imencode從/到內(nèi)存而不是文件讀寫圖像。

具有圖像的基本操作

訪問像素強度值

為了獲得像素強度值,您必須知道圖像的類型和通道數(shù)。以下是單通道灰度圖像(類型8UC1)和像素坐標(biāo)x和y的示例:

Scalar intensity = img.at<uchar>(y, x);

intensity.val [0]包含0到255之間的值。請注意x和y的順序。由于OpenCV中的圖像由與矩陣相同的結(jié)構(gòu)表示,所以對于兩種情況,我們使用相同的約定 - 基于0的行索引(或y坐標(biāo))首先出現(xiàn),并且基于0的列索引(或x坐標(biāo))跟隨它?;蛘撸梢允褂靡韵路枺?/p>

Scalar intensity = img.at<uchar>(Point(x, y));

現(xiàn)在讓我們考慮使用BGR顏色排序的3通道圖像(由imread返回的默認(rèn)格式):

Vec3b intensity = img.at < Vec3b >(y,x);
uchar blue = intensity.val [0];
uchar green = intensity.val [1];
uchar red = intensity.val [2];

您可以使用相同的浮點圖像方法(例如,您可以通過在3通道圖像上運行Sobel來獲取此類圖像):

(y,x); Vec3f intensity = img.at < Vec3f >(y,x);
float blue = intensity.val [0];
float green = intensity.val [1];
float red = intensity.val [2];

可以使用相同的方法來改變像素強度:

img.at < UCHAR >(Y,X)= 128;

OpenCV中有功能,特別是calib3d模塊,如projectPoints,它們以Mat的形式存在2D或3D數(shù)組。矩陣應(yīng)該只包含一列,每行對應(yīng)一個點,矩陣類型應(yīng)相應(yīng)為32FC2或32FC3。這樣一個矩陣可以很容易地構(gòu)造成std::vector

vector<Point2f> points;
//... fill the array
Mat pointsMat = Mat(points);

可以使用與Mat :: at相同的方法訪問此矩陣中的一個點:

Point2f point = pointsMat.at < Point2f >(i,0);

內(nèi)存管理和引用計數(shù)

Mat是一種保持矩陣/圖像特征(行和列數(shù),數(shù)據(jù)類型等)和指向數(shù)據(jù)的指針的結(jié)構(gòu)。所以沒有什么可以阻止我們有幾個Mat對應(yīng)于相同數(shù)據(jù)的實例。當(dāng)Mat的特定實例被破壞時,Mat保留一個引用計數(shù),指示數(shù)據(jù)是否必須被釋放。以下是創(chuàng)建兩個矩陣而不復(fù)制數(shù)據(jù)的示例:

std::vector<Point3f> points;
// .. fill the array
Mat pointsMat = Mat(points).reshape(1);

因此,我們得到一個32FC1矩陣與3列而不是32FC3矩陣與1列。pointsMat使用點數(shù)據(jù),銷毀時不會釋放內(nèi)存。然而,在這種特殊情況下,開發(fā)人員必須確保點的生命周期比pointMat長。如果我們需要復(fù)制數(shù)據(jù),可以使用例如cv :: Mat :: copyTocv :: Mat :: clone

Mat img = imread(“image.jpg”);
Mat img1 = img.clone();

相反,使用C API,必須由開發(fā)人員創(chuàng)建輸出圖像,可以向每個功能提供空輸出Mat。每個實現(xiàn)都為目標(biāo)矩陣調(diào)用Mat :: create。如果矩陣為空,則此方法分配數(shù)據(jù)。如果它不是空且具有正確的大小和類型,該方法什么都不做。然而,如果大小或類型與輸入?yún)?shù)不同,則數(shù)據(jù)被釋放(并丟失)并分配新的數(shù)據(jù)。例如:

Mat img = imread(“image.jpg”);
Mat sobelx;
Sobel(img,sobelx,CV_32F,1,0);

原始操作

在矩陣上定義了一些方便的操作符。例如,這里是我們?nèi)绾螐默F(xiàn)有的灰度圖像“img”制作黑色圖像:

img = Scalar(0);

選擇感興趣的區(qū)域:

Rect r(10, 10, 100, 100);
Mat smallImg = img(r);

從Mat到C API數(shù)據(jù)結(jié)構(gòu)的轉(zhuǎn)換:

Mat img = imread(“image.jpg”);
IplImage img1 = img;
CvMat m = img;

請注意,這里沒有數(shù)據(jù)復(fù)制。

從顏色到灰度的轉(zhuǎn)換:

Mat img = imread("image.jpg"); // loading a 8UC3 image
Mat grey;
cvtColor(img, grey, COLOR_BGR2GRAY);

將圖像類型從8UC1更改為32FC1:

src.convertTo(dst,CV_32F);

可視化圖像

在開發(fā)過程中看到算法的中間結(jié)果是非常有用的。OpenCV提供了可視化圖像的便捷方式??梢允褂靡韵路绞斤@示8U圖像:

Mat img = imread(“image.jpg”);
namedWindow(“image”,WINDOW_AUTOSIZE);
imshow(“image”,img);
waitKey();

waitKey()的調(diào)用會啟動一個消息傳遞循環(huán),等待“圖像”窗口中的關(guān)鍵筆劃。32F圖像需要轉(zhuǎn)換為8U型。例如:

Mat img = imread("image.jpg");
Mat grey;
cvtColor(img, grey, COLOR_BGR2GRAY);
Mat sobelx;
Sobel(grey, sobelx, CV_32F, 1, 0);
double minVal, maxVal;
minMaxLoc(sobelx, &minVal, &maxVal); //find minimum and maximum intensities
Mat draw;
sobelx.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
namedWindow("image", WINDOW_AUTOSIZE);
imshow("image", draw);
waitKey();
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號