国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

opencv學習筆記

2019-11-08 02:27:06
字體:
來源:轉載
供稿:網友

opencv學習筆記

標簽(空格分隔): 學習筆記


(1)操作像素

1.1對像素值的索引

1.1.1一維矩陣

if(iamge.channels()==1){image.at<uchar>(i,j);}

初始化矩陣的某一行

result.row(0).setTo(cv::Scalar(0));//單獨設置矩陣中某一行的像素值 result.row(result.rows - 1).setTo(cv::Scalar(0)); result.col(0).setTo(cv::Scalar(0)); result.col(result.cols - 1).setTo(cv::Scalar(0));

1.1.2多維矩陣(以RGB圖像為例)

if(image.channels()==3){image.at<cv::Vec3b>(i,j)[0]=255;image.at<cv::Vec3b>(i,j)[1]=255;image.at<cv::Vec3b>(i,j)[2]=255;//對三維矩陣的元素進行索引}

注:opencv還有二元素向量和四元素向量類型(cv::Vec2b和cv::Vec4b).同樣的,也有其他數據類型(如s代表short, i代表int,f代表float,d代表double.)所有的這些類型都是使用模板類cv::Vect

1.1.3擴展

使用CV::Mat的成員函數的返回值類型必須通過在調用時通過模板參數指定。因此,opencv提供了類cv::Mat_,此類的指針或者引用可以直接進項相互類型轉換。該類重載了()操作符。例:

cv::Mat_<uchar> impointer=image;//impointer指針指向image;impointer(50,100)=0;//直接索引到圖像矩陣的第50行,100列;

1.1.4 程序運用:對RGB圖像加入椒鹽噪聲

void Salt(cv::Mat &image, int n){ for (int k = 0; k < n; ++k) { //rand()隨機數生成 int i = rand() % image.rows; int j = rand() % image.cols; if (image.channels() == 1)//彩色圖 { image.at<uchar>(i, j) = 255; } if (image.channels() == 3)//灰度圖 { image.at<cv::Vec3b>(i, j)[0] = 255; image.at<cv::Vec3b>(i, j)[1] = 255; image.at<cv::Vec3b>(i, j)[2] = 255; } }}

1.2使用指針遍歷圖像

1.2.1 RGB圖片在opencv的存儲方式

圖像緩沖區的前面三個字節對應圖像左上角像素的三個通道值,接下來的三個字節對應第一行的第二個像素,以此類推。

1.2.2使用輸入輸出參數

在處理圖像時,如果不想圖片被改變,可以創建圖像的“深拷貝”。

iamge=cv::imread("baboon.png");//克隆圖像cv::Mat imageClone=image.clone();

或者使用create函數創建一個與輸入圖像的尺寸和類型相同的矩陣:

image.create(image.rows,image.cols,image.type());

注:create函數創建的圖像的內存都是連續的,create函數不會對圖像進行填補。要遍歷圖像需要使用兩個指針完成:

for(int i=0;i<image.rows;++i){ //得到圖像的第i行的首地址 const uchar*data_in=image.ptr<uchar>(i); uchar* data_out=result.ptr<uchar>(i); for(int j=0;j<image.cols*image.channels();++j) { //進行對每一個像素的處理 }}

1.2.3底層指針運算

cv::Mat形式的矩陣在內存中的存儲首地址可以通過data成員變量得到,且data是一個unsigned cahr型的指針:

uchar* data =image.data;

從當前行到下一行可以通過對指針加上行寬得到:

data += iamge.step;

可以通過下一行代碼調用i行j列像素地址

data = image.data+i*image.step+j*image.elemSize();//相當于常用的矩陣索引(i*cols+j),先定義到位置:i*image.step,再加上下一個元素所占的內存空間+j*image.elemSize()

1.3 使用迭代器遍歷圖像

一個圖像的迭代器可以這樣聲明:

cv::MatIterator_<cv::Vec3b>it;

或者

cv::Mat_<cv::Vec3b>::iterator it;

1.3.1使用迭代器遍歷圖像所有像素

//得到初始位置的迭代器cv::Mat_<cv::Vec3b>::iteraator it = image.begin<cv::Vec3b>();//得到終止位置的迭代器cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>();//遍歷所有像素for(;it!=itend;++it){(*it)[0]=...;(*it)[1]=...;(*it)[2]=...;}

1.3.2高效的圖像遍歷循環

void colorReduce(cv::Mat &image, int div = 64){ int nl = image.rows; int nc = image.cols; //判斷圖像是否連續存儲 if (image.isContinuous()) { nc = nc*nl;//把圖像拉成一維數組 nl = 1; } int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0)); uchar mask = 0xFF << n; for (int i = 0; i < nl; i++) { ucahr* data = image.ptr<uchar>(j); for (int i = 0; i < nc; i++) { //一次處理處理三個通道的一個像素 *data++ = *data&mask + dic / 2; *data++ = *data&mask + div / 2; *data++ = *data&mask + div / 2; } }}

1.3.3遍歷圖像和鄰域操作

通過獲取相鄰像素的指針對圖像進行銳化處理void sharpen(const cv::Mat &image, cv::Mat &result){ result.create(image.size(), image.type()); for (int i = 1; i < image.rows - 1; i++)//除了第一行和最后一行的所有行 { const uchar* PRevious = image.ptr<const uchar>(i - 1);//獲取圖像上一行的指針 const uchar* current = image.ptr<const uchar>(i);//獲取當前行的指針 const uchar* next = image.ptr<const uchar>(i + 1);//獲取下一行的指針 uchar *output = result.ptr<uchar>(i);//輸出行 for (int j = 1; j < image.cols - 1; j++) { *output = cv::saturate_cast<uchar>(5*current[j]-current[j-1]-current[j+1]-previous[j]-next[j]); output++; } } //將未處理的像素全部設置為0 result.row(0).setTo(cv::Scalar(0)); //單獨設置矩陣中某一行的像素值 result.row(result.rows - 1).setTo(cv::Scalar(0)); result.col(0).setTo(cv::Scalar(0)); result.col(result.cols - 1).setTo(cv::Scalar(0)); }

1.3.4把多維矩陣分層拉出

int main(){ cv::Mat image; image = cv::imread("baboon.png"); std::vector<cv::Mat>planes; cv::split(image, planes); cv::namedWindow("channel1"); cv::imshow("channel1", planes[0]); cv::namedWindow("channel2"); cv::imshow("channel2", planes[1]); cv::namedWindow("channel3"); cv::imshow("channel3", planes[2]); cv::waitKey(0);}

1.3.5 定義感興趣區域

方法一:使用cv::Rect cv::Rect須指定矩形左上角的坐標(構造函數的前兩個參數)和矩形的長寬(構造函數的后兩個參數)。 方法二:使用cv::Range cv::Range

//270,385是矩形左上角的坐標,logo.rows和logo.cols是矩形的長寬cv::Mat imageROI = image(cv::Range(270,270+logo.rows),cv::Range(385,385+logo.cols))

方法三:直接在原圖上定義

start,end為起始坐標cv::Mat imageROI = image.rowRange(start,end);cv::Mat imageROI = image.colRange(start,end);

(2)基于類的圖像處理

2.1面向對象的編程思想

2.1.1 示例程序:鑒定圖像中含有給定顏色的所有像素,并返回一個二值圖像,相同像素賦值255,其他像素賦值0;

//類定義class ColorDetector{private: int minDist; cv::Vec3b target; cv::Mat result;public://類方法申明 ColorDetector() :minDist(100){ //初始化默認參數 target[0] = target[1] = target[2] = 0; } cv::Mat process(const cv::Mat &image); int getDistance(const cv::Vec3b & color)const; void setColorDistanceThreshold(int distance); int setColorDistanceThreshold()const; void setTargetColor(unsigned char red, unsigned char green, unsigned char blue); cv::Vec3b getTargetColor()const; ~ColorDetector(){};};cv::Vec3b ColorDetector::getTargetColor()const{ return target;}void ColorDetector::setTargetColor(unsigned char red, unsigned char green, unsigned char blue){ //BGR順序 target[2] = red; target[1] = green; target[0] = blue;}void ColorDetector::setColorDistanceThreshold(int distance){ if (distance < 0) { distance = 0; } minDist = distance;}int ColorDetector::setColorDistanceThreshold()const{ return minDist;}int ColorDetector::getDistance(const cv::Vec3b & color)const{ return abs(color[0] - target[0]) + abs(color[1] - target[1]) + abs(color[2] - target[2]);} cv::Mat ColorDetector::process(const cv::Mat &image){ //按需重新分配二值圖像 //與輸入圖像的尺寸相同,但是只有一個通道 result.create(image.rows, image.cols, CV_8U); //得到迭代器 cv::Mat_<cv::Vec3b>::const_iterator it = image.begin<cv::Vec3b>(); cv::Mat_<cv::Vec3b>::const_iterator itend = image.end<cv::Vec3b>(); cv::Mat_<uchar>::iterator itout = result.begin<uchar>(); //處理每個像素 for (; it != itend; it++, itout++) { //計算每個像素和目標顏色的距離 if (getDistance(*it) < minDist) { *itout = 255; } else { *itout = 0; } } return result;}

測試程序

int main() { //創建圖像處理的對象 ColorDetector cdetect; //讀取輸入圖像 cv::Mat image = cv::imread("boldt.jpg"); if (!image.data) return 0; //設置輸入參數 cdetect.setTargetColor(130,190,230); cv::namedWindow("result"); //處理并顯示結果 cv::imshow("result", cdetect.process(image)); cv::waitKey(); return 0; }

處理結果

![輸出效果圖][2]

2.2%20圖像空間的轉換//RGB圖像空間轉換至LAB顏色空間cv::cvtColor(image,converted,CV_BGR2Lab);//RGB圖像空間轉換至YCbCr空間cv::cvtColor(image,converted,CV_BGR2YCrCb);//RGB圖像空間轉換至HSV圖形空間cv::cvtColor(image,converted,%20CV_BGR2HSV);//RGB圖像轉換為灰度圖cv::cvtColor(color,gray,CV_BGR2Gray);(3)使用直方圖統計像素3.1統計直方圖并顯示3.1.1直方圖統計類class%20Histgram1D{private:%20%20%20%20//項的數量、范圍、通道數%20%20%20%20int%20hist_size[1];%20%20%20%20float%20hist_range[2];%20%20%20%20const%20float*%20ranges[1];%20%20%20%20int%20channels[1];public:%20%20%20%20//準備1D直方圖的參數,創建構造函數%20%20%20%20Histgram1D()%20%20%20%20{%20%20%20%20%20%20%20%20hist_size[0]%20=%20256;%20%20%20%20%20%20%20%20hist_range[0]%20=%200.0;%20%20%20%20%20%20%20%20hist_range[1]%20=%20255.0;%20%20%20%20%20%20%20%20ranges[0]%20=%20hist_range;%20%20%20%20%20%20%20%20channels[0]%20=%200;%20%20%20%20}%20%20%20%20//定義獲取直方圖的函數%20%20%20%20cv::MatND%20getHistgram(const%20cv::Mat%20&%20image)%20%20%20%20{%20%20%20%20%20%20%20%20cv::MatND%20hist;%20%20%20%20%20%20%20%20//調用calcHist函數統計圖像的直方圖%20%20%20%20%20%20%20%20cv::calcHist(&image,%20%20%20%20//輸入圖像%20%20%20%20%20%20%20%20%20%20%20%201,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//輸入圖像的個數%20%20%20%20%20%20%20%20%20%20%20%20channels,%20%20%20%20%20%20%20%20%20%20%20//通道數%20%20%20%20%20%20%20%20%20%20%20%20cv::Mat(),%20%20%20%20%20%20%20%20%20%20//不使用圖像作為掩碼%20%20%20%20%20%20%20%20%20%20%20%20hist,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//返回的直方圖%20%20%20%20%20%20%20%20%20%20%20%201,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//1D直方圖%20%20%20%20%20%20%20%20%20%20%20%20hist_size,%20%20%20%20%20%20%20%20%20%20//項的數量%20%20%20%20%20%20%20%20%20%20%20%20ranges%20%20%20%20%20%20%20%20%20%20%20%20%20%20//像素值的范圍%20%20%20%20%20%20%20%20%20%20%20%20);%20%20%20%20%20%20%20%20%20%20%20%20return%20hist;%20%20%20%20}%20%20%20%20//定義繪制直方圖的函數%20%20%20%20cv::Mat%20getHistgramImage(const%20cv::Mat%20&%20image)%20%20%20%20{%20%20%20%20%20%20%20%20//首先獲得統計好的直方圖數據%20%20%20%20%20%20%20%20cv::MatND%20hist%20=%20getHistgram(image);%20%20%20%20%20%20%20%20//獲取直方圖邊界%20%20%20%20%20%20%20%20double%20max_value%20=%200;%20%20%20%20%20%20%20%20double%20min_value%20=%200;%20%20%20%20%20%20%20%20cv::minMaxLoc(hist,%20&min_value,%20&max_value,%200,%200);%20%20%20%20%20%20%20%20//顯示直方圖的圖像%20%20%20%20%20%20%20%20//創建一個大小為256*256,的矩陣,矩陣中的數值類型uchar,初始化為255%20%20%20%20%20%20%20%20cv::Mat%20histImg(hist_size[0],%20hist_size[0],%20CV_8U,%20cv::Scalar(255));%20%20%20%20%20%20%20%20//設置最高點為nbins的90%%20%20%20%20%20%20%20%20int%20high_pointer%20=%20static_cast<int>(0.9*hist_size[0]);%20%20%20%20%20%20%20%20//每個像素值都繪制一條垂直線%20%20%20%20%20%20%20%20for%20(int%20i%20=%200;%20i%20<%20hist_size[0];%20i++)%20%20%20%20%20%20%20%20{%20%20%20%20%20%20%20%20%20%20%20%20float%20bin_value%20=%20hist.at<float>(i);//獲取統計好的直方圖數據%20%20%20%20%20%20%20%20%20%20%20%20//定義垂直線%20%20%20%20%20%20%20%20%20%20%20%20int%20intensity%20=%20static_cast<int>(bin_value*high_pointer%20/%20max_value);%20%20%20%20%20%20%20%20%20%20%20%20//繪制垂直線%20%20%20%20%20%20%20%20%20%20%20%20cv::line(histImg,%20cv::Point(i,%20hist_size[0]),%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cv::Point(i,%20hist_size[0]%20-%20intensity),%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cv::Scalar::all(0));%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20return%20histImg;%20%20%20%20}};3.1.2測試函數int%20main(){%20%20%20%20cv::Mat%20image%20=%20cv::imread("lena.bmp", 0); if (!image.data) { //圖像未被成功打開 std::cout << "can not open this image!" << std::endl; exit(0); } //創建Histgram1D 類對象 Histgram1D CalcHist; //計算直方圖 cv::Mat histo = CalcHist.getHistgramImage(image); //遍歷每個條目 /*for (int i = 0; i < 256; i++) { std::cout << "Count[" << i << "]=" << histo.at<float>(i) << std::endl; }*/ //顯示直方圖 cv::namedWindow("Histgram"); cv::imshow("Histgram", histo); cv::waitKey(0); }

顯示結果如下圖:

直方圖

####3.1.3生成二值圖像的閾值函數 cv::Mat thresholded; cv::threshold(image,thresholded,60,255,cv::THRESH_BINARY); //(原圖,輸出圖,圖像閾值,像素灰度最大值,二值圖像格式)


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新余市| 日照市| 平谷区| 嵩明县| 合川市| 兰溪市| 文成县| 工布江达县| 新兴县| 蓬莱市| 东莞市| 龙口市| 夹江县| 玉龙| 香格里拉县| 普格县| 上犹县| 巴塘县| 邵武市| 油尖旺区| 津南区| 商丘市| 大化| 新闻| 康平县| 虹口区| 宁陵县| 依安县| 本溪| 平遥县| 合水县| 海兴县| 古交市| 砀山县| 宁阳县| 南乐县| 阆中市| 铜川市| 迁西县| 呼伦贝尔市| 芦山县|