日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
一文弄明白OpenCVMat中通道channels的作用

1. 介紹

openCV 是使用 Mat 進行存儲圖片,記錄各種像素信息。那么 Mat 中的像素是如何記錄和獲取的呢?

企業(yè)建站必須是能夠以充分展現(xiàn)企業(yè)形象為主要目的,是企業(yè)文化與產(chǎn)品對外擴展宣傳的重要窗口,一個合格的網(wǎng)站不僅僅能為公司帶來巨大的互聯(lián)網(wǎng)上的收集和信息發(fā)布平臺,創(chuàng)新互聯(lián)面向各種領域:成都地磅秤成都網(wǎng)站設計、營銷型網(wǎng)站建設解決方案、網(wǎng)站設計等建站排名服務。


在網(wǎng)上找到有很多是C語言寫的。在這里我想使用java的語法給大家介紹一下。

如何通過Mat獲取到指定區(qū)域的像素。RGB,BGR,HSV,GRAY等格式數(shù)據(jù)的獲取。

2. channels 通道

當我們使用Mat.channels() 方法,能夠得到當前 Mat 的通道數(shù)。 通常返回結(jié)果值為:1,2,3,4 這四個結(jié)果。

那么這個通道是什么東西呢?

我們知道,所有的圖像都是由一個個像素點堆積而成的。而一個像素點,又是由RGB顏色混合而成的。

每一種顏色就是一種通道。每個像素點是多個通道顏色的混合結(jié)果。

PS:知識點,RGB三原色可以混淆所有我們?nèi)庋劭梢砸姷降念伾?/p>

所以,當我們弄明白通道之后就能明白如何獲取Mat中指定坐標的顏色值了。

mat.rows() 是Y軸長度。

mat.cols() 是X軸長度。

示例:

Mat rgba ;// 假如我有一個 rgba的Mat對象
int channels = rgba.channels(); // channels 的長度是4
double[] temp = rgba.get(rgba.rows() / 2, rgba.cols() / 2); //取中間點顏色值
//temp 的數(shù)組的長度就是通道數(shù),所以它的length=4

當我們遍歷一遍temp的結(jié)果會得到:

StringBuffer stringBuffer = new StringBuffer();
for (double s : temp) {
stringBuffer.append(s).append(",");
}
Log.e("TAG", "顏色值:" + stringBuffer);

//輸出:
顏色值:3.0,0.0,4.0,255.0,

數(shù)據(jù)的結(jié)果實際情況是:

  • r:3.0
  • g:0.0
  • b:4.0
  • a:255  (透明度,0表示透明,255表示不透明)

知識點,OpenCV 中的顏色順序不是 BGR 格式么?這個順序不針對 Mat 中的顏色,而是我們使用 Scalar 的時候傳入的顏色順序是 BGR 順序而已。

new Scalar(10,255,255); //顏色順序是 B,G,R

我們?nèi)绻且粋€ BGR 格式的 Mat 對象那么顏色值會怎么顯示呢?

還是使用上面的 Mat 我們進行轉(zhuǎn)換之后,看看同一個點輸出的結(jié)果:

Mat bgr=new Mat();
Imgproc.cvtColor(rgba, bgr, Imgproc.COLOR_RGB2BGR);// 將RGB格式轉(zhuǎn)為BGR格式
int channels = bgr.channels(); // channels 的長度是3
double[] temp1 = bgr.get(bgr.rows() / 2, bgr.cols() / 2); //取中間點顏色值
StringBuffer stringBuffer1 = new StringBuffer();
for (double s : temp1) {
stringBuffer1.append(s).append(",");
}
Log.e("TAG", "顏色值:" + stringBuffer1);

//輸出:
顏色值:4.0,0.0,3.0

數(shù)據(jù)的結(jié)果實際情況是:

  • b:4.0
  • g:0.0
  • r:3.0

就會出現(xiàn)顏色的通道數(shù)變化。

不知道注意到了沒有,我上面是將rbga直接轉(zhuǎn)成了BGR。

在高位轉(zhuǎn)換的情況下,A通道會被直接丟棄。體現(xiàn)在圖像上就會沒有透明效果了。

我們?nèi)绻氪_保A通道也轉(zhuǎn)換,可以使用:

Imgproc.cvtColor(rgba, bgra, Imgproc.COLOR_RGBA2BGRA);

2.1 Gray 灰度圖轉(zhuǎn)換

當我們將RGBA或者BGR等彩色圖像轉(zhuǎn)換為GRAY灰色的時候,Mat的通道數(shù)就會被壓制為單通道G了。效果如下:

int channels = rgba.channels();
double[] temp = rgba.get(rgba.rows() / 2, rgba.cols() / 2); //取中間點顏色值
// temp的長度就是 channels的值,所以temp的結(jié)果就是4
StringBuffer stringBuffer = new StringBuffer();
for (double s : temp) {
stringBuffer.append( s).append(",");
}
Log.e("TAG", "通道數(shù):" + channels + " 顏色值:" + stringBuffer);

Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGBA2GRAY); //將RGBA轉(zhuǎn)GRAY
channels = rgba.channels();
temp = rgba.get(rgba.rows() / 2, rgba.cols() / 2); //取中間點顏色值
stringBuffer = new StringBuffer();
for (double s : temp) {
stringBuffer.append(s).append(",");
}
Log.e("TAG", "變換后:通道數(shù):" + channels + " 顏色值:" + stringBuffer);

//輸出結(jié)果:
E/TAG: 通道數(shù):4 顏色值:43.0,48.0,69.0,255.0,
E/TAG: 變換后:通道數(shù):1 顏色值:49.0,

會發(fā)現(xiàn)灰色圖是只有一個通道的。

按照Gray = R*0.299 + G*0.587 + B*0.114 公式進行的轉(zhuǎn)換。

這個公式叫做Luminosity(亮度算法)。這個算法中RGB的各占比例。都是一個經(jīng)驗值。也就是說沒有科學道理。純粹經(jīng)驗出發(fā)調(diào)試出來的一個比例。

PS:所以有一個小常識,RGB轉(zhuǎn)Gray,然后再Gray轉(zhuǎn)換回RGB會出現(xiàn)色差。因為在轉(zhuǎn)換過程中避免不了信息丟失。

2.2 小結(jié)

當我們弄明白通道數(shù)的概念之后。就能夠弄明白cvtColor中的各種轉(zhuǎn)換了

Luv,Lab,HSV,RGB,BGR,HLS,YUV,GRAY等等的顏色轉(zhuǎn)換其實都是針對我們的單像素中的通道值在處理。

  1. 單通道的,是Gray灰度圖。
  2. 雙通道的,兩個通道值一個為實數(shù),個為虛數(shù)。主要是RGB555和RGB565格式的圖像,這個通道通常用來計算。
  3. 三通道的,圖片就是彩色圖像了,例如RGB,BGR,HSV,HLS等等。
  4. 四通道的,圖片帶透明度的圖像了。相較于三通道多了一個alpha通道,也就是表示透明度。

我們在使用OpenCV時,新手經(jīng)常出現(xiàn)Mat錯誤,就在于通道轉(zhuǎn)換了。因為OpenCV有些算法是必須單通道的。而我們一不小心傳了3通道的?;蛘撸琈at是三通道的。與另一個單通道的Mat進行比較處理時,出現(xiàn)通道錯誤等等。

注意:

我們使用Imgproc.cvtColor?方法進行轉(zhuǎn)換的時候。輸入的Imgproc.COLOR_RGBA2GRAY等等值是很重要的。需要根據(jù)我們的Mat的實際情況進行選擇。

我們?nèi)绻鸐at是BGR格式的,我們卻選擇使用Imgproc.COLOR_RGB2HSV_FULL轉(zhuǎn)換,雖然結(jié)果是轉(zhuǎn)換了。但是實際情況是不對的。

因為Imgproc會按照RGB的順序從double[]數(shù)組中提取參數(shù)進行計算處理,而不是按照BGR的格式進行提取轉(zhuǎn)換。

2.2.1 Imgproc.COLOR_XXXX解釋

簡單介紹下ImgProc.COLOR_XXX的信息。其實說破很簡單:

ImgProc.COLOR_BGR2BGRA;// BGR to BGRA 也就是BGR格式轉(zhuǎn)BGRA格式
ImgProc.COLOR_RGB2RGBA;// RGB to RGBA 也就是RGB格式轉(zhuǎn)RGBA格式
ImgProc.COLOR_BGRA2BGR;// BGRA to BGR 格式
ImgProc.COLOR_RGBA2BGR;// RGBA to BGR 格式
ImgProc.COLOR_BGRA2GRAY;// BGRA to GRAY 格式
ImgProc.COLOR_RGB2HSV;// RGB to HSV格式 H的范圍值是0-180
ImgProc.COLOR_RGB2HSV_FULL;// RGB to HSV_FULL格式 H的范圍值是0-360 (PS:FULL獲取更大的精度,消耗更多的內(nèi)存)

其他的就不介紹了,命名中的2代表to。然后將左邊的顏色格式轉(zhuǎn)為右邊的顏色格式而已。

3. 通道分解和合成

我們?nèi)绻氩僮魍ǖ?。有很多方法,最簡單的是我們直接遍歷然后修改通道參數(shù):

Mat det;
double [] temp;
for(int y=0;y for(int x=0;x temp = det.get(x,y);
//根據(jù)通道情況,修改值
}
}

或者,我們直接修改指定位置的顏色值:mat.put(x,y,temp);

而我們?nèi)绻肱酷槍νǖ肋M行操作,可以使用OpenCV提供的算法:

Core.split(); //分解通道
Core.merge(); //合成通道
Core.mixChannels(); //通道拆分復制 上面兩個分解和合成是該函數(shù)的一種特例場景。

下面來介紹這三個方法的傳值:

Core.split(Mat m, List mv) 
//Mat m :需要進行通道分解的源Mat
//List mv: 將源Mat的每個通道拆解為單通道的Mat,我們?nèi)绻苯訉⒃揕ist中的Mat進行顯示將會全部是灰色的(因為是單通道了)

使用:

List defList=new ArrayList<>();
Core.split(rgba,defList);
for(Mat mat:defList){
//我們得到的都是單通道的Mat。 如果直接轉(zhuǎn)Bitmap顯示 將只會看到灰度圖
}

我們?nèi)绻胫幌肟吹組at中的紅色通道的效果,而不是看灰度圖。該怎么處理?

需要結(jié)合split方法和merge方法一起使用

Core.merge(List mv, Mat dst)
//List mv: 需要合并的Mat的集合,會將全部的mat的通道合并到dst中去 List中的Mat 必須寬高相同,
//dst:輸出的Mat:它的寬高必須和List中的Mat的寬高相同。而通道數(shù)會是List中所有Mat的通道數(shù)的總和

使用:將上面split拆解的Mat進行合并

//創(chuàng)建單通道 CvType.CV_8UC1
Mat blackMat = new Mat(rgba.size(), CvType.CV_8UC1, new Scalar(0)); //繪制一個全黑的Mat
List mergeList = new ArrayList<>();
//創(chuàng)建一個3通道的 Mat對象
Mat dst = new Mat(rgba.size(), CvType.CV_8UC3);
mergeList.add(blackMat); //B 通道黑色
mergeList.add(blackMat); //G 通道黑色
mergeList.add(defList.get(0));// R通道
Core.merge(mergeList, dst);

最終我們得到的dst就是一個三通道的圖像了,只有R通道有值。(圖片是BGR的順序存儲的)

4. 總結(jié)

到這里關(guān)于通道的介紹就結(jié)束了。以上內(nèi)容基于自己的理解和驗證。在openCV4.6 SDK版本,java開發(fā)環(huán)境下進行的驗證。


文章名稱:一文弄明白OpenCVMat中通道channels的作用
當前網(wǎng)址:http://www.5511xx.com/article/dpgjcgj.html