說到圖像像素,肯定要先認識一下圖像中的坐標系長什么樣。
1. 坐標體系中的零點坐標為圖片的左上角,X軸為圖像矩形的上面那條水平線;Y軸為圖像矩形左邊的那條垂直線。該坐標體系在諸如結構體Mat,Rect,Point中都是適用的。(OpenCV中有些數據結構的坐標原點是在圖片的左下角,可以設置的)。
2. 在使用image.at<TP>(x1, x2)來訪問圖像中點的值的時候,x1並不是圖片中對應點的x軸坐標,而是圖片中對應點的y坐標(也就是編程中的pic.rows那行)。x2同理。
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。
5 多通道的圖像可以直接賦值,不必每個通道賦值。但是要注意其類型是Vec3b,如果寫成uchar,最后的copy圖像只會顯示源圖像的1/3
char *tempPath="0.jpg"; Mat src=imread(tempPath); Mat copy=Mat::zeros(src.rows,src.cols,src.type()); for (int nrows=0;nrows<src.rows;nrows++) { for (int ncols=0;ncols<src.cols;ncols++) { copy.at<Vec3b>(nrows,ncols)=src.at<Vec3b>(nrows,ncols); } }
Mat src=imread("image/color.jpg"); imshow("a",src); int i,j; int cPointR,cPointG,cPointB,cPoint;//currentPoint;
for(i=1;i<src.rows;i++) for(j=1;j<src.cols;j++) { cPointB=src.at<Vec3b>(i,j)[0]; cPointG=src.at<Vec3b>(i,j)[1]; cPointR=src.at<Vec3b>(i,j)[2]; if(cPointB>100&cPointR<100&cPointG<100) { src.at<Vec3b>(i,j)[0]=0; //單通道是uchar,沒有[0][1][2]
src.at<Vec3b>(i,j)[1]=0; src.at<Vec3b>(i,j)[2]=0; } } imshow("da",src);
注意每個點的像素灰度值cPointR,cPointG,cPointB,cPoint的數據類型是int,在單通道圖內由於讀取像素灰度值的代碼是img.at<uchar>(nrows,ncols),所以特別容易把數據類型記成unsigned char型
============================================================
【轉】VC++讀取圖像RGB值(未試驗)
#include <iostream> #include <fstream> #include <string> #include <windows.h> #include <gdiplus.h> #pragma comment(lib, "gdiplus.lib") using namespace std; using namespace Gdiplus; int main() { GdiplusStartupInput gdiplusstartupinput; ULONG_PTR gdiplustoken; GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, NULL); wstring infilename(L"1.jpg"); string outfilename("color.txt"); Bitmap* bmp = new Bitmap(infilename.c_str()); UINT height = bmp->GetHeight(); UINT width = bmp->GetWidth(); cout << "width " << width << ", height " << height << endl; Color color; ofstream fout(outfilename.c_str()); for (UINT y = 0; y < height; y++) for (UINT x = 0; x < width ; x++) { bmp->GetPixel(x, y, &color); fout << x << "," << y << ";" << (int)color.GetRed() << "," << (int)color.GetGreen() << "," << (int)color.GetBlue() << endl; } fout.close(); delete bmp; GdiplusShutdown(gdiplustoken); return 0; }
關於數據的儲存:(轉)
Mat_<uchar>對應的是CV_8U,Mat_<char>對應的是CV_8S,Mat_<int>對應的是CV_32S,Mat_<float>對應的是CV_32F,Mat_<double>對應的是CV_64F,對應的數據深度如下:
• CV_8U - 8-bit unsigned integers ( 0..255 )
• CV_8S - 8-bit signed integers ( -128..127 )
• CV_16U - 16-bit unsigned integers ( 0..65535 )
• CV_16S - 16-bit signed integers ( -32768..32767 )
• CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
• CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
• CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
這里還需要注意一個問題,很多OpenCV的函數支持的數據深度只有8位和32位的,所以要少使用CV_64F,但是vs的編譯器又會把float數據自動變成double型,有些不太爽。
