【opencv4.3.0教程】07之像素基本操作 2 讀寫像素

目錄

一、前言

二、溫故知新——像素基本操作

1、獲取像素指針

1.灰度圖

2.彩色圖像

2、像素範圍處理

三、讀寫像素

1、讀像素

2、寫像素

四、代碼實戰


一、前言

從上一篇文章開始,我們走進了像素操作的世界,然後我們講解了最基本的像素操作,爲什麼是最基本的呢?

我們做像素操作,無非就是獲取到像素,然後修改像素,然後展示效果。這些步驟裏面,都需要通過像素指針去進行操作,然後操作過程中,要保證像素範圍是在合法區域的。也就是不管什麼操作,都需要基於我們昨天講的兩個最基本操作。

今天我們要講的是讀寫像素,就是在獲取到圖像像素指針之後的兩個基本操作。讓我們一起,複習一下上一篇文章講的基本操作,然後一起走進今天的內容吧!

二、溫故知新——像素基本操作

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;
		}
	}

那我們得到的圖片是:

 

大家也可以自己隨心修改一些像素值看一下效果呀!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章