1. 程式人生 > >學習Opencv 2.4.9(二) ---操作像素

學習Opencv 2.4.9(二) ---操作像素

椒鹽噪聲 window align 是個 簡單 ++ ima opencv2 mar

作者:咕唧咕唧liukun321

來自:http://blog.csdn.net/liukun321


本質上說一張圖像就是由數值組成的矩陣。Opencv 2.x由 cv::Mat 這個數據結構來表示一張圖像。矩陣的每個元素代表了一個像素。對於彩色圖像而言矩陣的元素是一個三元數。

對圖像有了這個新的認識,以下能夠試著借助opencv處理圖像了。

先來看一下今天要處理的圖像:

技術分享

今天的主題是存取像素,首先來看一下怎樣存取像素值。事實上對於像素值的操作都能夠由cv::Mat類中成員直接或間接實現,cv::Mat有若幹成員函數能夠獲取圖像的數據及屬性。

操作單個像素方法:

at(int y int x)

cv::mat的成員函數: at(int y int x)能夠用來存取圖像中相應坐標為(x,y)的元素坐標。

可是在使用它時要註意,在編譯期必須要已知圖像的數據類型,這是由於cv::mat能夠存放隨意數據類型的元素。因此at方法的實現是用模板函數來實現的。

用法:假設提前已知一幅圖像img的數據類型為 unsigned char型灰度圖(單通道),要對坐標為(10,12)的像素又一次賦值為128,則相應操作例如以下:


img.at<uchar>(12,10) = 128;


假設要操作的圖片img是一幅數據類型相同為unsigned char的彩色圖片,再次要求將坐標(10,12)的像素賦值為128。這個操作跟上面的就有點差別了,須要對這個像素三個通道的每個相應元素賦值,Opencv中圖像三原色在內存中的排列順序為B-G-R(見以下凝視),操作步驟例如以下:

img.at<cv::Vec3b>(12,10) [0]= 128;//B
img.at< cv::Vec3b >(12,10) [1]= 128;//G
img.at< cv::Vec3b >(12,10) [2]= 128;//R

了解了at方法的用法,以下就嘗試一下使用at方法對剛才的圖片做一個簡單的處理(將圖像中增加椒鹽噪點)。椒鹽噪點是一種特殊的噪點,是隨機的將圖像的部分像素設置為黑色或白色。

既然灰度圖與彩色圖像對單個元素的操作方式不同,這就須要有一個圖像類型推斷的過程。

cv::Mat image = cv::imread("test.jpg");
if(image.channles() == 1)
{
	//灰度圖
}else{
	//彩色圖
}

清楚了這些過程。以下就來看看增加椒鹽噪點函數的實現過程:

#include <opencv2/opencv.hpp>
#include<cstdlib>
using namespace cv;

void salt(Mat &img,int saltNum)
{
	int x,y;
	int i ;
	for(i = 0;i < saltNum; i++)
		{
			x = rand()%img.cols;
			y = rand()%img.rows;
			
			if(img.channels() == 1)
				{
					img.at<uchar>(y,x) = 255;
				}else if(img.channels() == 3)
				{
					img.at<Vec3b>(y,x)[0] = 255;
					img.at<Vec3b>(y,x)[1] = 255;
					img.at<Vec3b>(y,x)[2] = 255;	
				}
		}

}
int main()
{
	Mat image = imread("../test.jpg");
	
	 Mat result;
	result = image.clone();
	salt(result,3000);
	namedWindow("src(http://blog.csdn.net/liukun321)" , CV_WINDOW_AUTOSIZE);
	imshow("src(http://blog.csdn.net/liukun321)", image);
	imshow("dst(http://blog.csdn.net/liukun321)", result);
	waitKey();
	return 0;
}

程序執行後的效果圖:

原圖

技術分享


增加椒鹽噪聲後效果

技術分享

事實上除了at方法操作像素,還能夠使用opencv提供的類cv::Mat_ 來實現。

cv::Mat_是一個模板子類。

這個類定義了非常多額外的方法,可是沒有提供公共的成員變量。假設已知了矩陣的類型,使用cv::Mat_會帶來非常多便利。它的用法例如以下:

cv::Mat_<uchar>  img = imread("test.jpg");
img(10,12) = 128;//10行 12列

另一種操作像素的方法:使用Mat類的ptr()方法配合cols 、rows、step、elemSize等成員變量,直接進行指針操作。以下先來說說這幾個成員變量

cols代表圖像的列數

rows代表圖像的高度

step 代表以字節為單位的圖像寬度

elemSize 代表像素的大小 (比方一個三通道uchar 型矩陣,返回值為3)

prt()方法相同是個模板類。須要編譯期已知像素點的類型:

cv::Mat_<uchar>  img = imread("test.jpg");
uchar* addr =  img.ptr<uchar>(10);//返回10行的地址
addr +=12;//單通道灰度圖
*addr = 128;


相同完畢了對第10行第12列像素的操作。

若圖象為三通道彩色圖:


cv::Mat_<uchar>  img = imread("test.jpg");
uchar* addr =  img.ptr<uchar>(10);//返回10行的地址
addr +=12* img.elemSize。//單通道灰度圖
*addr = 128;

addr +=12* img.elemSize是由於彩色圖象在內存中的存儲方式:圖像緩沖區中的前三個字節相應圖像左上角第一個像素的三個通道值。接下來的三個字節相應第一行的第二個像素。以此類推。

並且註意Opencv默認是使用BGR的通道順序。

到此已經介紹了3中操作圖像中像素的方法。

除這三種以外另一種使用叠代器的操作。今天就不再介紹了。



學習Opencv 2.4.9(二) ---操作像素