目錄
一、前言
從上一篇文章開始,我們走進了像素操作的世界,然後我們講解了最基本的像素操作,爲什麼是最基本的呢?
我們做像素操作,無非就是獲取到像素,然後修改像素,然後展示效果。這些步驟裏面,都需要通過像素指針去進行操作,然後操作過程中,要保證像素範圍是在合法區域的。也就是不管什麼操作,都需要基於我們昨天講的兩個最基本操作。
今天我們要講的是讀寫像素,就是在獲取到圖像像素指針之後的兩個基本操作。讓我們一起,複習一下上一篇文章講的基本操作,然後一起走進今天的內容吧!
二、溫故知新——像素基本操作
1、獲取像素指針
獲取像素指針包括獲取灰度圖像像素指針和彩色圖像像素指針。
1.灰度圖
對於灰度圖,我們有如下兩種方式獲取像素指針:
一種是以行列座標訪問,前面是行,後面是列;
一種是以點座標訪問,前面是x軸,後面是y軸;
src_gray.at<uchar>(y, x); //行在前,列在後,y表示行,x表示列
src_gray.at<uchar>(Point(x, y));
2.彩色圖像
對於彩色圖像,我們要使用一個類型Vec3b來獲取三個通道的數值,然後分別賦給三個整型變量,或者直接賦值給Scalar類型數據:
Vec3b BGR = src.at<Vec3b>(row, col);
int B = BGR.val[0];
int G = BGR.val[1];
int R = BGR.val[2];
Scalar BGR1 = src.at<Vec3b>(Point(col, row));
2、像素範圍處理
然後我們需要考慮像素範圍是0-255,所以我們要控制像素範圍,在OpenCV中,我們使用下面的API來控制範圍,遵循的原則如下:
小於0,返回值爲0;
大於255,返回值爲255;
其他,返回其本身。
saturate_cast<uchar>(number);
三、讀寫像素
1、讀像素
讀像素比較簡單,其實我們在講獲取像素指針的時候,就不可避免的要涉及到讀像素。因爲只有我們定義的像素指針成功讀取到像素,我們才能知道我們定義的像素指針是沒有問題的。所以我們在講像素指針的實戰時候,其實就是在讀像素。
讀像素的操作包括如下:
1.加載圖像;
2.使用像素指針獲取像素;
3.獲取每個通道的值;
對於灰度圖像來說,因爲只有一個通道,我們可以將最後兩步合併,直接將像素指針的值賦給int類型的數據就獲取到了通道的值。
2、寫像素
當我們可以讀取到像素的時候,那我們最先能想到的操作應該就是修改像素了吧。
寫像素是像素操作中最基本的操作,就是通過賦值的方式直接修改像素值。
//灰度圖像
image.at<uchar>(y, x) = 123;
//彩色圖像
image.at<Vec3b>(y,x)[0]=0; // blue
image.at<Vec3b>(y,x)[1]=0; // green
image.at<Vec3b>(y,x)[2]=255; // red
當然,如果我們想修改一幅圖像上的全部像素值,我們還可以選擇一個更爲直接的方法,使用Scalar直接修改圖像的全部像素顏色。
src = Scalar(0, 0, 255);
四、代碼實戰
爲了方便大家對上面知識有更加深刻的理解,我們通過一個實例來感受一下:
我們對一幅彩色圖像的像素進行讀取和修改,看一下他們的效果:
Mat src = imread("./image/sign.png");
if (!src.data)
{
cout << "ERROR : could not load image.\n";
return -1;
}
imshow("init_src", src);
//讀像素
for (int i = 0; i < src.rows; i+= src.rows/5)
{
for (int j = 0; j < src.cols; j+= src.cols / 5)
{
Vec3b BGR = src.at<Vec3b>(i, j);
int B = BGR.val[0];
int G = BGR.val[1];
int R = BGR.val[2];
cout << "[" << B << ", " << G << ", " << R << "]\t";
}
cout << endl;
}
//寫像素
for (int i = 0; i < src.rows; i += 5)
{
for (int j = 0; j < src.cols; j += 5)
{
src.at<Vec3b>(i, j)[0] = 0;
src.at<Vec3b>(i, j)[1];
src.at<Vec3b>(i, j)[2] = 0;
}
}
imshow("new_src", src);
如果我們修改第一通道和第三通道的像素值,圖片就會如下所示(隔點修改像素值):
如果我們圖片上的全部像素值修改:
//寫像素
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
src.at<Vec3b>(i, j)[0];
src.at<Vec3b>(i, j)[1] = 0;
src.at<Vec3b>(i, j)[2] = 0;
}
}
那我們得到的圖片是:
大家也可以自己隨心修改一些像素值看一下效果呀!