1. 程式人生 > >OpenCV(二)如何對影象的畫素進行操作

OpenCV(二)如何對影象的畫素進行操作

對影象的畫素進行操作,我們可以實現空間增強,反色等目的。讓我們先來看一下記憶體空間中影象矩陣,也就是Mat的矩陣數值部分是怎麼儲存的:

如果影象是一幅灰度影象,他就像這樣,從左到右,從上到下,依次是矩陣的每一行每一列,這時候矩陣M(i,j)的值自然就是當前點的灰度值了。

而對於一幅彩色影象,由於它的畫素分量channel並不是一個,所以每一列又分為了幾個channel。拿常見的RGB影象來說,就像這樣:

從這張圖上,就可以比較清楚地看出來在記憶體中矩陣是如何儲存多channel影象的了。這裡要注意的是在RGB模型中,每一個子列依次為BGR,也就是正好是顛倒的,第一個分量是藍色,第二個是綠色,第三個是紅色。

清楚了影象在記憶體中的儲存方式,我們也就可以來進行畫素值的操作了。在這裡,我們舉這樣一個例子。我們對一幅灰度影象的灰度值進行變換:

小於100的灰度值被統一對映為0;100到200之間的灰度值被對映為100;大於200的灰度值被對映為200.

主函式如下:

int main()
{
	string picName="lena.jpg";
	Mat A=imread (picName,CV_LOAD_IMAGE_GRAYSCALE);    //讀入灰度影象
	uchar table[256];          //對映表,規定了變換前後灰度值的對應關係 table[gray_value_before]=gray_value_after
	for (int i=0;i<256;i++)
	{
		table[i]=i/100*100;   //這裡利用了C++的語言特性i/100只會留下整數部分
	}
	imshow("變換前",A);
	Mat B=ChangeImg (A,table);    //變換函式
	imshow ("變換後",B);
	waitKey ();
	return 0;
}


首先,我們用指標方式對影象的畫素點灰度值進行操作:
Mat  ChangeImg(Mat &img,const uchar* table)
{
	CV_Assert(img.depth ()!=sizeof(uchar));  //宣告只對深度8bit的影象操作
	int channels=img.channels ();            //獲取影象channel
	int nrows=img.rows;                     //矩陣的行數
	int ncols=img.cols*channels;             //矩陣的總列數=列數*channel分量數
	if (img.isContinuous ())               //判斷矩陣是否連續,若連續,我們相當於只需要遍歷一個一維陣列
	{
		ncols*=nrows;
		nrows=1;                 //一維陣列
	}
	//遍歷畫素點灰度值
	for (int i=0;i<nrows;i++)
	{
		uchar *p=img.ptr<uchar>(i);    //獲取行地址
		for (int j=0;j<ncols;j++)
		{
			p[j]=table[p[j]];           //修改灰度值
		}
	}
	return img;
}

這裡,我們獲取了每一行開始處的指標,然後遍歷至該行末尾。如果矩陣是以連續方式儲存的,我們只需請求一次指標、然後一路遍歷下去就行。彩色影象的情況有必要加以注意:因為三個通道的原因,我們需要遍歷的元素數目也是3倍。

或者,我們可以使用data。data會從Mat中返回指向矩陣第一行第一列的指標。注意如果該指標為NULL則表明物件裡面無輸入,所以這是一種簡單的檢查影象是否被成功讀入的方法。當矩陣是連續儲存時,我們就可以通過遍歷 data 來掃描整個影象。例如,一個灰度影象,其操作如下:

uchar* p = img.data;
for( unsigned int i =0; i < ncol*nrows; ++i)
	*p++ = table[*p];

或者,更安全的方法,我們可以使用迭代器。在迭代法中,所需要做的僅僅是獲得影象矩陣的begin和end,然後增加迭代直至從begin到end。將*操作符新增在迭代指標前,即可訪問當前指向的內容。
Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
{
    // accept only char type matrices
    CV_Assert(I.depth() != sizeof(uchar));     
    
    const int channels = I.channels();
    switch(channels)
    {
    case 1: 
        {
            MatIterator_<uchar> it, end; 
            for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
                *it = table[*it];
            break;
        }
    case 3: 
        {
            MatIterator_<Vec3b> it, end; 
            for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
            {
                (*it)[0] = table[(*it)[0]];
                (*it)[1] = table[(*it)[1]];
                (*it)[2] = table[(*it)[2]];
            }
        }
    }
    
    return I; 
}

注意,在這裡對3通道的影象進行操作的時候,使用到了Vec3b。Vec3b作為一個對三元向量的資料結構,用在這裡正好是能夠表示RGB的三個分量。如果對於彩色影象,仍然用uchar的話,則只能獲得3通道中的B分量。比如我們可以這樣打印出影象的RGB三個分量:
for (int i=0;i<img.rows;i++)
	{
		const Vec3b* Mpoint=img.ptr <Vec3b>(i);
		for (int j=0;j<img.cols;j++)
		{
			Vec3b intensity=*(Mpoint+j);
			cout<<"R:"<<int(intensity[2])<<" G"<<int(intensity[1])<<" B"<<int(intensity[0])<<"    ";
		}
		cout<<endl;
	}

這裡使用指標,當然也可以使用上面的迭代器。

然而,OpenCV裡面已經有了相應函式可以讓我們更加方便地對畫素進行操作,那便是LUT函式,而且推薦使用OpenCV的內建函式,因為已經針對晶片做了優化設計,使得速度有很大提升。

函式原型為:void LUT(InputArray src, InputArray lut, OutputArray dst, int interpolation=0 )

實現的對映關係如下所示:


也就是說比如原來src中值為1會對映為table[1]所對應的值再加上d。

所以上面的操作,我們其實只需要使用LUT函式就可以了。結合我們自己設計的table表,就能夠實現對影象的操作。

int main()
{
	string picName="lena.jpg";
	Mat A=imread (picName,CV_LOAD_IMAGE_GRAYSCALE);    //讀入灰度影象
	Mat lookUpLut(1,256,CV_8UC1);   //建立一個256個元素的對映表
	imshow ("變換前",A);
	for (int i=0;i<256;i++)
	{
		lookUpLut.at<uchar>(i)=i/100*100;
	}
	Mat B;
	LUT (A,lookUpLut,B);
	imshow ("變換後",B);
	waitKey ();
	return 0;
}

下面的圖就是效果啦~~~



相關推薦

Python-OpenCV 處理影象影象操作

https://segmentfault.com/a/1190000003742442 0x01. 畫素 有兩種直接操作圖片畫素點的方法: 第一種辦法就是將一張圖片看成一個多維的list,例如對於一張圖片im,想要操作第四行第四列的畫素點就直接 im[3,3] 就可以獲取到這個點的RGB值。 第二種就是

opencv影象進行操作

用Opencv對影象畫素進行操作大概有以下三種方式: 1. One using the Inbuilt macro 2. One using the pointer to the image data 3. Getting the raw data from the image. =============

OpenCV學習筆記影象的提取

     提取影象的畫素及畫素索引 Mat src, dst; src = imread("mountainandwater.jpg"); //讀取影象 if (src.empty()) { qDebug()<<"can

python數字影象處理3影象的訪問與裁剪

圖片讀入程式中後,是以numpy陣列存在的。因此對numpy陣列的一切功能,對圖片也適用。對陣列元素的訪問,實際上就是對圖片畫素點的訪問。 彩色圖片訪問方式為: img[i,j,c] i表示圖片的行數,j表示圖片的列數,c表示圖片的通道數(RGB三通道分別對應0,1

opencv影象進行簡單算術運算加減乘除

opencv可以將影象以不同的方式組合,影象其實就是一般的矩陣,所以它們可以做加減乘除。opencv提供了各種影象算術操作符。1【首先我們對兩幅影象進行操作】當我們需要一些影象特效或者在影象上疊加資訊時,就需要用到影象加法。我們只需呼叫cv::add函式就可以完成,更準確的說

Azure Application Gateway後端 VM 進行負載均衡

一,引言   上一節有講到使用 Azure Application Gateway 為我們後端型別為 Web App 的 Demo 專案提供負載均衡,Azure Application Gateway 的後端池的目標型別可以是多中型別,如下圖所示: 目標型別分別是: 1,IP address or FQD

Azure Front Door後端 VM 進行負載均衡

一,引言   上一篇我們講到通過 Azure Front Door 為我們的 Azure App Service 提供流量轉發,而整個 Azure Front Door 在新增後端池的時候可選的後端型別是支援多種Azure Service,如下圖所示: 目標型別可為: 1,App Service(應用服務

OpenCV如何影象進行操作

對影象的畫素進行操作,我們可以實現空間增強,反色等目的。讓我們先來看一下記憶體空間中影象矩陣,也就是Mat的矩陣數值部分是怎麼儲存的: 如果影象是一幅灰度影象,他就像這樣,從左到右,從上到下,依次是矩陣的每一行每一列,這時候矩陣M(i,j)的值自然就是當前點的灰度值了。

【程式語言】利用CImage類影象的處理影象值化

    最近做的課程作業需要用到CImage函式處理影象,其中涉及到讀取影象以及對影象畫素進行操作,在這裡記錄一下自己的理解。    首先是CImage類的定義和讀取圖片 CImage srcImage; CImage dstImage; CString path = "

[Unity3D] 2D遊戲 準備影象素材並認識預製件Prefab

回顧 上一篇:(一) Hello Unity! 在初步認識了Unity之後,我們成功建立了第一個2D畫素精靈——我們的主角Player,並且匯入添加了一個LittleBuddy作為主角的載體。 構思 當我們打算繼續的時候,會陷入一種茫然:之

OpenCV值化影象操作

二值化影象畫素不是0就是255,資料型別為uchar。所以訪問方法是: // 這裡inputmat是二值化影象的mat inputmat.at<uchar>(y, x); 判斷是否為白色的方法: if (inputmat.at<uchar&g

opencv影象點訪問的三種方法利用程式進行解讀

程式碼放到自己的工程中,執行就可以的 #include <opencv2\opencv.hpp> #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #includ

OpenCV-Python 影象處理影象的讀取、顯示與儲存

說明: 本系列主要是學習OpenCV-Python文件的個人筆記。 很少有理論的敘述,都是函式名、引數描述、作用、應用場景、程式碼、效果圖。簡單明瞭,即學即用。 目標 學會讀取、顯示、儲存單張影象 對應的函式分佈為:cv2.imread() ,

Java 並發編程象的不變性和安全的公布

不一致 字段 更新 要求 nts ava 然而 caching mut 一、不變性 滿足同步需求的還有一種方法是使用不可變對象(Immutable Object)。到眼下為止,我們介紹了很多與原子性和可見性相關的問題,比如得到失效數據。丟失更新操作

selenium+python自動化測試瀏覽器的簡單操作

cat quit 報錯 簡單 conn port ted href ide 1.最大化 maximize_window 1 # coding = utf-8 2 3 from selenium import webdriver 4 chromedriver =

淺談前端效能優化——HTTP傳輸進行壓縮

1、前端效能優化的一點: 對js、css、圖片等進行壓縮,儘可能減小檔案的大小,減少檔案下載的時間,從而減少網頁響應的時間。   2、前端效能優化的另一點: 對HTTP傳輸進行壓縮,即在js,css、圖片等資源已經壓縮的基礎上(其實,檔案的壓縮與否均可,檔案的壓縮跟HTTP傳輸過程的壓縮沒關

OpenCV——LUT顏色空間縮減

LUT是look up table的縮寫,中文解釋:顯示查詢表,實際意義很簡單易懂。 舉個例子,如果是單通道的影象,灰度梯度是0~255,即分為256級。 你可以設定對應灰度轉化成你設定成的灰度 table[256]; table[0] = 2; table[1] = 5; 像上圖就

淺談JavaSE效能優化1——BufferedImage與級渲染

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

opencv 1顯示影象,圖片123.jpg放在同一個資料夾內

#include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using namespace std; using namespace cv; int main() { Mat img =

OpenCV

1. 前言:Mat類簡介   OpenCV 作為強大的計算機視覺開源庫,很大程度上參考了MatLab的實現細節和語法風格,比如說,在OpenCV2.x版本以後,越來越多的函式實現了MatLab所具有的功能,甚至乾脆連函式名都一模一樣(如 imread, imshow,imwriter等)。   在計算機記