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等)。 在計算機記