1. 程式人生 > >基礎學習筆記之opencv(23):OpenCV座標體系的初步認識

基礎學習筆記之opencv(23):OpenCV座標體系的初步認識

轉自:http://www.cnblogs.com/tornadomeet/archive/2012/12/12/2813939.html

查詢資料的時候發現作者的文章,發現很細緻,留著備查。

前言

  相信很多朋友在使用OpenCV的時候會遇到一個小問題,且有時候對這樣的小問題沒有引起足夠的重視,或者通過表面想當然的去程式設計,所以除錯程式碼時出現一些莫名其妙的問題,最後發現問題時時間已經過去了一大把。最近我在除錯一個專案時就遇到過這種情況,即Mat::at(x,y)和Mat::at(Point(x, y))的區別,我在專案中把這2種看成效果一樣的,結果這個問題除錯時糾結了2天(因為該工程有關OpenCV的程式碼有上千行,且沒有懷疑這兩者的區別,因此有時候出現一些莫名其妙的結果,花了很多時間才找問題所在)。其實關於Mat的at訪問時這2者的區別我以前也做過筆記,只是此時不小心忘記了。這次專門為這個寫篇小筆記,提醒下自己。

  開發環境:OpenCV2.4.3+QtCreator2.5.1

  實驗基礎

  本次實驗通過一個簡短的例子,主要來說明下面4個問題:

  1. 座標體系中的零點座標為圖片的左上角,X軸為影象矩形的上面那條水平線;Y軸為影象矩形左邊的那條垂直線。該座標體系在諸如結構體Mat,Rect,Point中都是適用的。(雖然網上有學著說OpenCV中有些資料結構的座標原點是在圖片的左下角,但是我暫時還沒碰到過)。

  2. 在使用image.at<TP>(x1, x2)來訪問影象中點的值的時候,x1並不是圖片中對應點的x軸座標,而是圖片中對應點的y座標。因此其訪問的結果其實是訪問image影象中的Point(x2, x1)點,即與image.at<TP>(Point(x2, x1))效果相同。

  3. 如果所畫影象是多通道的,比如說image影象的通道數時n,則使用Mat::at(x, y)時,其x的範圍依舊是0到image的height,而y的取值範圍則是0到image的width乘以n,因為這個時候是有n個通道,所以每個畫素需要佔有n列。但是如果在同樣的情況下,使用Mat::at(point)來訪問的話,則這時候可以不用考慮通道的個數,因為你要賦值給獲取Mat::at(point)的值時,都不是一個數字,而是一個對應的n維向量。

  4. 多通道影象在使用minMaxLoc()函式是不能給出其最大最小值座標的,因為每個畫素點其實有多個座標,所以是不會給出的。因此在程式設計時,這2個位置應該給NULL。

  實驗程式碼及註釋

  main.cpp:

複製程式碼
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat image, image_3c;
    image.create(Size(256, 256), CV_8UC1);
    image_3c.create(Size(256, 256), CV_8UC3);   //3通道的影象
    image.setTo(0);
    image_3c.setTo(0);

    image.at<uchar>(10, 200) = 255; //使用at函式的地方,用的是10,200
    Point point(20, 100);
    image.at<uchar>(point) = 250;//使用at函式的地方,用的是Point(10,200)

    image_3c.at<uchar>(10, 300) = 255;
    image_3c.at<uchar>(10, 302) = 254;
    Point point_3c(20, 200);
    image_3c.at<uchar>(point_3c) = 250;

    double maxVal = 0; //最大值一定要賦初值,否則執行時會報錯
    Point maxLoc;
    minMaxLoc(image, NULL, &maxVal, NULL, &maxLoc);
    cout << "單通道影象最大值: " << maxVal << endl;
    double min_3c, max_3c;
    //注意多通道在使用minMaxLoc()函式是不能給出其最大最小值座標的,因為每個畫素點其實有多個座標,所以是不會給出的
    minMaxLoc(image_3c, &min_3c, &max_3c, NULL, NULL);
    cout << "3通道影象最大值: " << max_3c << endl;

    imshow("image", image);
    imshow("image_3c", image_3c);
    waitKey(0);
    return 0;
}
複製程式碼

  實驗結果:

  單通道影象的輸出結果如下所示:

  

  由上圖可以看出,黑色的影象中有2個白色的點(讀者可以仔細看下,由於只有1個畫素點,所以需要自己找下,呵呵)的位置是不同的,因此可以證明Mat::at(x,y)和Mat::at(Point(x, y))是有區別的。

  3通道影象的輸出結果如下所示:

  

  由上圖可以看出,3通道的影象也是有2個點的,但是程式中在使用Mat::at(x, y)其y的值為300和302,這已經超出了影象的寬度256。這同時證明了實驗基礎中的第3點。

  後臺輸出結果如下:

  

  實驗總結:由此可見,平時一定要注意一些細節上的東西。