1. 程式人生 > >opencv--畫素值的讀寫

opencv--畫素值的讀寫

畫素值的讀寫

我們需要讀取某個畫素值,或者設定某個畫素值;在更多的時候,我們需要對整個影象裡的所有畫素進行遍歷。OpenCV 提供了多種方法來實現影象的遍歷。

at()函式

函式at()用於讀取矩陣中的某個畫素,或者對某個畫素進行賦值操作。

uchar value = grayim.at<uchar>(i,j);//讀出第 i 行第 j 列畫素值
grayim.at<uchar>(i,j)=128; //將第 i 行第 j 列畫素值設定為 128

如果要對影象進行遍歷,可以參考下面的例程。這個例程建立了兩個影象,
分別是單通道的 grayim 以及 3 個通道的 colorim,然後對兩個影象的所有畫素值
進行賦值,最後現實結果。

#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
	Mat grayim(600, 800, CV_8UC1);
	Mat colorim(600, 800, CV_8UC3);
	//遍歷所有畫素,並設定畫素值
	for (int i = 0; i < grayim.rows; ++i)
		for (int j = 0; j < grayim.cols; ++j)
			grayim.at<
uchar>(i, j) = (i + j) % 255; //遍歷所有畫素,並設定畫素值 for (int i = 0; i < colorim.rows; ++i) for (int j = 0; j < colorim.cols; ++j) { Vec3b pixel; pixel[0] = i % 255; //Blue pixel[1] = j % 255; //Green pixel[2] = 0; //Red colorim.at<Vec3b>(i, j) = pixel; } //顯示結果 imshow("grayim", grayim)
; imshow("colorim", colorim); waitKey(0); return 0; }

在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述在這裡插入圖片描述
在這裡插入圖片描述

#include"opencv2/opencv.hpp"
#include<iostream>
using  namespace std;
using namespace cv;
int main() {
	Mat src;
	src = imread("D:/111.jpg");
	if (src.empty()) {
		cerr << "open error" << endl;
		return -1;
	}
	imshow("src", src);

	Mat g_src1;
	cvtColor(src, g_src1, CV_BGR2GRAY);
	imshow("g_src1", g_src1);

	Mat c_src;
	src.copyTo(c_src);
	imshow("c_src",c_src);

	int height = src.rows;
	int weight = src.cols;
	int channals = src.channels();//3

	for (int row = 0; row < height; row++) {
		for (int col = 0; col < weight; col++) {
			if (channals == 1) {
				int date=g_src1.at<uchar>(row, col);
				g_src1.at<uchar>(row, col) = 255 - date;
			}
			else if(channals==3 ){
				int b = c_src.at<Vec3b>(row, col)[0];
				int g = c_src.at<Vec3b>(row, col)[1];
				int r = c_src.at<Vec3b>(row, col)[2];
				c_src.at<Vec3b>(row, col)[0] = 0;
				c_src.at<Vec3b>(row, col)[1] = g;
				c_src.at<Vec3b>(row, col)[2] = b;

				//把三通道的值轉化成單通道
				//取最大的值作為灰度值
				g_src1.at<uchar>(row, col) = max(r, max(g, b));
			}
		}
	}
	//把三通道位運算取反
	Mat dst;
	bitwise_not(src, dst);
	imshow("c_src_1", c_src);
	imshow("dst", dst);
	waitKey(0);
	return 0;

}

在這裡插入圖片描述

使用迭代器

如果你熟悉 C++的 STL 庫,那一定了解迭代器(iterator)的使用。迭代器可以方便地遍歷所有元素。Mat 也增加了迭代器的支援,以便於矩陣元素的遍歷。下面的例程功能跟上一節的例程類似,但是由於使用了迭代器,而不是使用行數和列數來遍歷,所以這兒沒有了 i 和 j 變數,影象的畫素值設定為一個隨機數。

#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
	Mat grayim(600, 800, CV_8UC1);
	Mat colorim(600, 800, CV_8UC3);

	//遍歷所有畫素,並設定畫素值
	MatIterator_<uchar> grayit, grayend;

	for (grayit = grayim.begin<uchar>(), grayend =grayim.end<uchar>(); grayit != grayend; ++grayit)
			*grayit = rand() % 255;

	//遍歷所有畫素,並設定畫素值
	MatIterator_<Vec3b> colorit, colorend;
	for (colorit = colorim.begin<Vec3b>(), colorend =colorim.end<Vec3b>(); colorit != colorend; ++colorit)
	{
		(*colorit)[0] = rand() % 255; //Blue
		(*colorit)[1] = rand() % 255; //Green
		(*colorit)[2] = rand() % 255; //Red
	}
	//顯示結果
	imshow("grayim", grayim);
	imshow("colorim", colorim);
	waitKey(0);
	return 0;
}

在這裡插入圖片描述

通過資料指標

使用 IplImage 結構的時候,我們會經常使用資料指標來直接操作畫素。通過指標操作來訪問畫素是非常高效的,但是你務必十分地小心。C/C++中的指標操作是不進行型別以及越界檢查的,如果指標訪問出錯,程式執行時有時候可能看上去一切正常,有時候卻突然彈出“段錯誤”(segment fault)。

當程式規模較大,且邏輯複雜時,查詢指標錯誤十分困難。對於不熟悉指標的程式設計者來說,指標就如同噩夢。如果你對指標使用沒有自信,則不建議直接通過指標操作來訪問畫素。雖然 at()函式和迭代器也不能保證對畫素訪問進行充分的檢查,但是總是比指標操作要可靠一些。如果你非常注重程式的執行速度,那麼遍歷畫素時,建議使用指標。

下面的例程演示如何使用指標來遍歷影象中的所有畫素。

#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
	Mat grayim(600, 800, CV_8UC1);
	Mat colorim(600, 800, CV_8UC3);
	//遍歷所有畫素,並設定畫素值
	for (int i = 0; i < grayim.rows; ++i)
	{
		//獲取第 i 行首畫素指標
		uchar * p = grayim.ptr<uchar>(i);
		//對第 i 行的每個畫素(byte)操作
		for (int j = 0; j < grayim.cols; ++j)
			p[j] = (i + j) % 255;
	}


	//遍歷所有畫素,並設定畫素值
	for (int i = 0; i < colorim.rows; ++i)
	{
		//獲取第 i 行首畫素指標
		Vec3b * p = colorim.ptr<Vec3b>(i);
		for (int j = 0; j < colorim.cols; ++j)
		{
			p[j][0] = i % 255; //Blue
			p[j][1] = j % 255; //Green
			p[j][2] = 0; //Red
		}
		
	}
	//顯示結果
	imshow("grayim", grayim);
	imshow("colorim", colorim);
	waitKey(0);
	return 0;
}