亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Opencv分水嶺算法學(xué)習(xí)

 更新時(shí)間:2018年01月23日 11:22:52   作者:丶Minskyli  
這篇文章主要為大家詳細(xì)介紹了Opencv分水嶺算法的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

分水嶺算法可以將圖像中的邊緣轉(zhuǎn)化成“山脈”,將均勻區(qū)域轉(zhuǎn)化為“山谷”,這樣有助于分割目標(biāo)。

分水嶺算法是一種基于拓?fù)淅碚摰臄?shù)學(xué)形態(tài)學(xué)的分割方法,其基本思想是把圖像看作是測(cè)地學(xué)上的拓?fù)涞孛玻瑘D像中的每一點(diǎn)像素的灰度值表示該點(diǎn)的海拔高度,每一個(gè)局部極小值及其影響區(qū)域稱(chēng)為集水盆,而集水盆的邊界則形成分水嶺。分水嶺的概念和形成可以通過(guò)模擬浸入過(guò)程來(lái)說(shuō)明:在每一個(gè)局部極小值表面,刺穿一個(gè)小孔,然后把整個(gè)模型慢慢浸入水中,隨著浸入的加深,每一個(gè)局部極小值的影響區(qū)域慢慢向外擴(kuò)展,在兩個(gè)集水盆匯合處構(gòu)筑大壩,即形成分水嶺。

分水嶺的計(jì)算過(guò)程是一個(gè)迭代標(biāo)注過(guò)程。分水嶺計(jì)算分成兩個(gè)步驟:一個(gè)是排序過(guò)程,一個(gè)是淹沒(méi)過(guò)程。首先對(duì)每個(gè)像素的灰度級(jí)進(jìn)行從低到高的排序,然后在從低到高實(shí)現(xiàn)淹沒(méi)的過(guò)程中,對(duì)每一個(gè)局部極小值在h階高度的影響域采用先進(jìn)先出(FIFO)結(jié)構(gòu)進(jìn)行判斷及標(biāo)注。分水嶺變換得到的是輸入圖像的集水盆圖像,集水盆之間的邊界點(diǎn)即為分水嶺。顯然,分水嶺表示的是輸入圖像的極大值點(diǎn)。

簡(jiǎn)而言之,分水嶺算法首先計(jì)算灰度圖的梯度,這對(duì)圖像中的“山谷”或沒(méi)有紋理的“盆地”(亮度值低的點(diǎn))的形成是很有效的,也對(duì)“山頭”或圖像中有主導(dǎo)線段的“山脈”(山脊對(duì)應(yīng)的邊緣)的形成有效。然后開(kāi)始從用戶(hù)指定點(diǎn)(或者算法得到點(diǎn))開(kāi)始持續(xù)“灌注”盆地直到這些區(qū)域連成一片。基于這樣產(chǎn)生的標(biāo)記就可以把區(qū)域合并到0一起,合并后的區(qū)域又通過(guò)聚集的方式進(jìn)行分割,好像圖像被“填充”起來(lái)一樣。

實(shí)現(xiàn)分水嶺算法–watershed函數(shù)

函數(shù)watershed實(shí)現(xiàn)的分水嶺算法是基于標(biāo)記的分割算法中的一種。在把圖像傳給函數(shù)之前,需要大致勾畫(huà)標(biāo)記出圖像中的期望進(jìn)行分割的區(qū)域,它們被標(biāo)記為正指數(shù),所以,每一個(gè)區(qū)域都會(huì)被標(biāo)記為像素值1、2、3等,表示成為一個(gè)或者多個(gè)連接組件,這些標(biāo)記的值可以使用findContours函數(shù)和drawContours函數(shù)由二進(jìn)制的掩碼檢索出來(lái)。這些標(biāo)記就是即將繪制出來(lái)的分割區(qū)域的“種子”,而沒(méi)有標(biāo)記清楚的區(qū)域,被置為0,在函數(shù)的輸出中,每一個(gè)標(biāo)記中的像素被設(shè)置為“種子”的值,而區(qū)域間的值被設(shè)置為-1。
void watershed(inputArray,intputOutputArray markers)
*第一個(gè)參數(shù),輸入圖像,需為8位三通道的彩色圖像。
*第二個(gè)參數(shù),函數(shù)調(diào)用后的運(yùn)算結(jié)果存在這里,輸入/輸入32位單通道圖像的標(biāo)記結(jié)果。

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>

using namespace cv;
using namespace std;
//宏定義
#define WINDOW_NAME "image[procedure window]"

//全局變量聲明
Mat g_srcImage,g_maskImage;
Point prevPt(-1,-1);

//全局函數(shù)聲明
static void on_Mouse(int event,int x,int y,int flags,void*);

//主函數(shù)
int main()
{
  //載入源圖像
  g_srcImage=imread("/Users/new/Desktop/1.jpg");
  if(!g_srcImage.data){printf("讀取源圖像srcImage錯(cuò)誤~!\n");return false;}

  //顯示源圖像
  imshow(WINDOW_NAME,g_srcImage);
  Mat srcImage,grayImage;
  g_srcImage.copyTo(srcImage);
  //灰度化
  cvtColor(srcImage, g_maskImage, COLOR_BGR2GRAY);
  //imshow("image[mask]",g_maskImage);
  cvtColor(g_maskImage, grayImage, COLOR_GRAY2BGR);
  //imshow("image[gray]",grayImage);
  //掩膜圖像初始化為0
  g_maskImage=Scalar::all(0);

  //設(shè)置鼠標(biāo)回調(diào)函數(shù)
  setMouseCallback(WINDOW_NAME, on_Mouse,0);

  //輪詢(xún)按鍵處理
  while(1)
  {
    //獲取鍵值
    int c=waitKey(0);
    //若按鍵為ESC時(shí),退出
    if((char)c == 27)
      break;
    //若按鍵為2時(shí),恢復(fù)原圖
    if((char)c=='2')
    {
      g_maskImage=Scalar::all(0);
      srcImage.copyTo(g_srcImage);
      imshow("image",g_srcImage);
    }
    //若按鍵為1,則進(jìn)行處理
    if((char)c=='1')
    {
      //定義一些參數(shù)
      int i,j,compCount=0;
      vector<vector<Point>>contours;
      vector<Vec4i> hierarchy;
      //尋找輪廓
      findContours(g_maskImage, contours, hierarchy, CV_RETR_CCOMP, CHAIN_APPROX_SIMPLE);
      //輪廓為空時(shí)的處理
      if(contours.empty())
        continue;
      //復(fù)制掩膜
      Mat maskImage(g_maskImage.size(),CV_32S);
      maskImage=Scalar::all(0);

      //循環(huán)繪制輪廓
      for(int index=0;index>=0;index=hierarchy[index][0],++compCount)
        drawContours(maskImage, contours, index, Scalar::all(compCount+1),-1,8,hierarchy,INT_MAX);
        //compCount為零時(shí)的處理
        if(compCount==0)
          continue;

        //生成隨機(jī)顏色
        vector<Vec3b>colorTab;
        for(int i=0;i<compCount;++i)
        {
          int b=theRNG().uniform(0, 255);
          int g=theRNG().uniform(0, 255);
          int r=theRNG().uniform(0, 255);

          colorTab.push_back(Vec3b((uchar)b,(uchar)g,(uchar)r));
        }
        //計(jì)算處理時(shí)間并輸出到窗口中
        double dTime=(double)getTickCount();
        //進(jìn)行分水嶺算法
        watershed(srcImage, maskImage);
        dTime=(double)getTickCount()-dTime;
        printf("\t 處理時(shí)間=%gms\n",dTime*1000./getTickFrequency());
        //雙層循環(huán),將分水嶺圖像遍歷存入watershedImage中
        Mat watershedImage(maskImage.size(),CV_8UC3);
        for(i=0;i<maskImage.rows;++i)
          for(j=0;j<maskImage.cols;++j)
          {
            int index=maskImage.at<int>(i,j);
            if(index==-1)
              watershedImage.at<Vec3b>(i,j)=Vec3b(255,255,255);//圖像變白色
            else if(index<=0||index>compCount)
              watershedImage.at<Vec3b>(i,j)=Vec3b(0,0,0);//圖像變黑色
            else
              watershedImage.at<Vec3b>(i,j)=colorTab[index-1];
          }
        //混合灰度圖和分水嶺效果圖并顯示最終的窗口
        watershedImage=watershedImage*0.5+grayImage*0.5;
        imshow("image[watershed]",watershedImage);
    }
  }
    return 0;
}

//回調(diào)函數(shù)定義
void on_Mouse(int event,int x,int y,int flags,void*)
{
  //處理鼠標(biāo)不在窗口中的情況
  if(x<0||x>=g_srcImage.cols||y<0||y>=g_srcImage.rows)
    return;

  //處理鼠標(biāo)左鍵相關(guān)消息
  if(event==EVENT_LBUTTONUP||!(flags & EVENT_FLAG_LBUTTON))//按下左鍵
    prevPt=Point(-1,-1);
  else if(event==EVENT_LBUTTONDOWN)//松開(kāi)左鍵
    prevPt=Point(x,y);//鼠標(biāo)所指的位置

  //鼠標(biāo)左鍵按下并移動(dòng),繪制出白色線條
  else if(event==EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
  {
    Point pt(x,y);
    if(prevPt.x<0)//如果指出去了,返回
      prevPt=pt;
    line(g_maskImage, prevPt, pt, Scalar::all(255),2,8,0);//畫(huà)白線
    line(g_srcImage,prevPt,pt,Scalar::all(255),2,8,0);//畫(huà)白線
    prevPt=pt;
    imshow(WINDOW_NAME, g_srcImage);

  }
}


Opencv技巧

(1)計(jì)算算法運(yùn)行時(shí)間:

//計(jì)算處理時(shí)間并輸出到窗口中
        double dTime=(double)getTickCount();
        //進(jìn)行分水嶺算法
        watershed(srcImage, maskImage);
        dTime=(double)getTickCount()-dTime;
        printf("\t 處理時(shí)間=%gms\n",dTime*1000./getTickFrequency());

(2)改變圖像某點(diǎn)像素值:Mat類(lèi)中的at方法對(duì)于獲取圖像矩陣某點(diǎn)的RGB值或者改變某點(diǎn)的值很方便,

對(duì)于單通道的圖像:image.at<uchar>(i, j)
對(duì)于RGB通道的圖像:image.at<Vec3b>(i, j)[0] 
         image.at<Vec3b>(i, j)[1] 
         image.at<Vec3b>(i, j)[2]

(3)Point(-1,-1)解析:由于卷積過(guò)程,圖像矩陣要進(jìn)行填充,Point(-1,-1)即代表卷積開(kāi)始的位置,這決定了不填充時(shí)的結(jié)果A處于填充后結(jié)果B的位置的那個(gè)部分,從(-1,-1)開(kāi)始卷積的結(jié)果是A處于B的正中間那塊位置。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • c++ class中成員與分配內(nèi)存的問(wèn)題詳解

    c++ class中成員與分配內(nèi)存的問(wèn)題詳解

    很多人都知道C++類(lèi)是由結(jié)構(gòu)體發(fā)展得來(lái)的,所以他們的成員變量(C語(yǔ)言的結(jié)構(gòu)體只有成員變量)的內(nèi)存分配機(jī)制是一樣的,下面這篇文章主要給大家介紹了關(guān)于c++ class中成員與分配內(nèi)存問(wèn)題的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • C++深入講解對(duì)象的銷(xiāo)毀之析構(gòu)函數(shù)

    C++深入講解對(duì)象的銷(xiāo)毀之析構(gòu)函數(shù)

    構(gòu)造函數(shù)在創(chuàng)建對(duì)象時(shí)被系統(tǒng)自動(dòng)調(diào)用,而析構(gòu)函數(shù)(Destructor)在對(duì)象被撤銷(xiāo)時(shí)被自動(dòng)調(diào)用,相比構(gòu)造函數(shù),析構(gòu)函數(shù)要簡(jiǎn)單的多
    2022-04-04
  • C語(yǔ)言結(jié)構(gòu)體數(shù)組同時(shí)賦值的另類(lèi)用法

    C語(yǔ)言結(jié)構(gòu)體數(shù)組同時(shí)賦值的另類(lèi)用法

    今天小編就為大家分享一篇關(guān)于C語(yǔ)言結(jié)構(gòu)體數(shù)組同時(shí)賦值的另類(lèi)用法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • C++實(shí)現(xiàn)PatchMatch圖像修復(fù)算法

    C++實(shí)現(xiàn)PatchMatch圖像修復(fù)算法

    這篇文章主要介紹了C++實(shí)現(xiàn)PatchMatch圖像修復(fù)算法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • C++事件驅(qū)動(dòng)型銀行排隊(duì)模擬

    C++事件驅(qū)動(dòng)型銀行排隊(duì)模擬

    這篇文章主要為大家詳細(xì)介紹了C++事件驅(qū)動(dòng)型銀行排隊(duì)模擬,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • 嵌入式項(xiàng)目使用C語(yǔ)言結(jié)構(gòu)體位段特性實(shí)現(xiàn)斷言宏校驗(yàn)數(shù)據(jù)范圍有效性的方法

    嵌入式項(xiàng)目使用C語(yǔ)言結(jié)構(gòu)體位段特性實(shí)現(xiàn)斷言宏校驗(yàn)數(shù)據(jù)范圍有效性的方法

    今天小編就為大家分享一篇關(guān)于嵌入式項(xiàng)目使用C語(yǔ)言結(jié)構(gòu)體位段特性實(shí)現(xiàn)斷言宏校驗(yàn)數(shù)據(jù)范圍有效性的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • C語(yǔ)言實(shí)現(xiàn)家庭理財(cái)系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)家庭理財(cái)系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)家庭理財(cái)系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C++實(shí)現(xiàn)LeetCode(191.位1的個(gè)數(shù))

    C++實(shí)現(xiàn)LeetCode(191.位1的個(gè)數(shù))

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(191.位1的個(gè)數(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 《C++ primer plus》讀書(shū)筆記(二)

    《C++ primer plus》讀書(shū)筆記(二)

    本讀書(shū)筆記是讀了《C++ primer plus(第六版)》第五至八章的學(xué)習(xí)筆記。是C++讀書(shū)筆記系列的第二篇。復(fù)習(xí)C++基礎(chǔ)知識(shí)的可以瞄瞄。
    2014-10-10
  • C++線程中幾類(lèi)鎖的詳解

    C++線程中幾類(lèi)鎖的詳解

    這篇文章主要為大家介紹了C++線程中幾類(lèi)鎖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-11-11

最新評(píng)論