opencv 影象讀取顯示和畫素操作
阿新 • • 發佈:2019-01-06
從今天起,開始從頭系統學習下opencv,下面記錄下影象的基本操作:
1. 影象的讀取和顯示
Mat image = imread(imagePath, 1);
第二個引數表示圖片讀入的方式(flags可以預設,預設時flags=1,表示以彩色圖片方式讀入圖片)
flags>0時表示以彩色方式讀入圖片
flags=0時表示以灰度圖方式讀入圖片
flags<0時表示以圖片的本來的格式讀入圖片。
char *f = "E:\\opencv\\sources\\samples\\wp8\\OpenCVXaml\\OpenCVXaml\\Assets\\Lena.png";
Mat lena;
lena = imread(f);
imshow("lena", lena);
IplImage * lena2;
//lena2 = cvLoadImage(f, CV_LOAD_IMAGE_GRAYSCALE); // 載入灰度圖
lena2 = cvLoadImage(f, CV_LOAD_IMAGE_UNCHANGED);//載入原始影象
cvNamedWindow("lena2", CV_WINDOW_AUTOSIZE);//建立視窗
cvShowImage("lena2", lena2);
-
-
畫素讀取和操作
1. 利用cv::Mat的at函式,直接訪問具體地址
void get_setImagePixel(char *imagePath , int x , int y)
{
// Mat image = imread(imagePath , 0);
Mat image = imread(imagePath, 1);
//得寬高
int w = image.cols;
int h = image.rows;
int channels = image.channels();
if (x < w && y < h)
{
//灰度圖,畫素為單通道
if (channels == 1)
{
int pixel = image.at<uchar>(x, y);
cout << "灰度影象,處的灰度值為" << pixel << endl;
}
else
{
//通過實驗,彩色影象的預設儲存是bgr, 且儲存的格式如下
//讀取
int b = image.at<Vec3b>(x, y)[0]; // b = image.at<uchar>(x,y*3);
cout << b << endl;
int g = image.at<Vec3b>(x, y)[1]; //g = image.at<uchar>(x, y * 3 + 1);
cout << g << endl;
int r = image.at<Vec3b>(x, y)[2]; //r = image.at<uchar>(x, y * 3 + 1);
cout << r << endl;
//設定畫素值
image.at<Vec3b>(x, y)[0] = 255;
image.at<Vec3b>(x, y)[1] = 255;
image.at<Vec3b>(x, y)[2] = 255;
}
}
imshow("cc", image);
}
2. 利用Mat 的prt 函式:行首地址訪問
void get_setImagePixel2(char *imagePath, int x, int y)
{
Mat image = imread(imagePath, 1);
//得寬高
int w = image.cols;
int h = image.rows;
int channels = image.channels();
//如果影象連續 ,可以將資料轉化為1維陣列,提高訪問效率,但對少量畫素訪問就沒必要
//if (image.isContinuous())
//{
// //reshape函式用於改變矩陣維度
// //影象行數為1,列數為原先的行數乘上列數
// image.reshape(1, image.cols*image.rows);
//}
//獲得第y行的首地址
uchar *data = image.ptr<uchar>(y);
int position = x*channels;
if (channels == 1)
{
int pixel = data[position];
cout << "灰度影象,處的灰度值為" << pixel << endl;
}
else
{
//通過實驗,彩色影象的預設儲存是bgr, 且儲存的格式如下
//讀取
int b = data[position];
cout << b << endl;
int g = data[position+1];
cout << g << endl;
int r = data[position+2];
cout << r << endl;
//設定畫素值
data[position] = 255;
data[position+1] = 255;
data[position+2] = 255;
}
imshow("cc", image);
}
3. 利用迭代器遍歷影象
void get_setImagePixel3(char *imagePath, int x, int y)
{
Mat image = imread(imagePath, 1);
//得寬高
int w = image.cols;
int h = image.rows;
int channels = image.channels();
if (channels == 1)
{
//得到初始位置的迭代器
Mat_<uchar>::iterator it = image.begin<uchar>();
//得到終止位置的迭代器
Mat_<uchar>::iterator itend = image.end<uchar>();
int pixel = *(it + y * w + x);
cout << "灰度影象,處的灰度值為" << pixel << endl;
}
else
{
//得到初始位置的迭代器
Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
//得到終止位置的迭代器
Mat_<Vec3b>::iterator itend = image.end<Vec3b>();
//讀取
it = it + y * w + x;
int b = (*it)[0];
cout << b << endl;
int g = (*it)[1];
cout << g << endl;
int r = (*it)[2];
cout << r << endl;
//設定畫素值
(*it)[0] = 255;
(*it)[1] = 255;
(*it)[2] = 255;
}
imshow("cc", image);
}
若是大量訪問資料和更改資料時用第二種方式效率高。
Node: 在修改畫素時候,最好先用變數儲存,設定好了再賦值給Mat成員物件,如data,因為如果直接進行操作時,當一個分量值大於255時,向前進1的原則,則會修改前面畫素的值,如下:
void colorReduce(cv::Mat&image, int div)
{
int nl = image.rows; //影象的行數
//影象每行的畫素數
int nc = image.cols * image.channels();
for (int j = 0; j<nl; j++)
{
//得到第j行的首地址
uchar* data = image.ptr<uchar>(j);
//遍歷每行的畫素
for (int i = 0; i<nc; i++)
{
//printf("%d ", data[i]);
//data[i] = data[i] / div*div + 6;// 這裡需要用c來儲存,因為如果大於255時會向前進1,則影響前面的畫素,data[i] 會自己變得小255
int c = data[i] / div*div + 100;
data[i] = c > 255 ? 255 : c; //將每個畫素值都變為div的倍數,即將顏色數縮減了div倍
}
}
}