真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Opencv如何實現(xiàn)分水嶺算法-創(chuàng)新互聯(lián)

這篇文章將為大家詳細講解有關Opencv如何實現(xiàn)分水嶺算法,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)專注于企業(yè)營銷型網(wǎng)站、網(wǎng)站重做改版、資源網(wǎng)站定制設計、自適應品牌網(wǎng)站建設、HTML5建站、商城系統(tǒng)網(wǎng)站開發(fā)、集團公司官網(wǎng)建設、外貿(mào)網(wǎng)站建設、高端網(wǎng)站制作、響應式網(wǎng)頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為資源等各大城市提供網(wǎng)站開發(fā)制作服務。

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

分水嶺算法是一種基于拓撲理論的數(shù)學形態(tài)學的分割方法,其基本思想是把圖像看作是測地學上的拓撲地貌,圖像中的每一點像素的灰度值表示該點的海拔高度,每一個局部極小值及其影響區(qū)域稱為集水盆,而集水盆的邊界則形成分水嶺。分水嶺的概念和形成可以通過模擬浸入過程來說明:在每一個局部極小值表面,刺穿一個小孔,然后把整個模型慢慢浸入水中,隨著浸入的加深,每一個局部極小值的影響區(qū)域慢慢向外擴展,在兩個集水盆匯合處構筑大壩,即形成分水嶺。

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

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

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

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

#include
#include
#include

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錯誤~!\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);

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

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

        //生成隨機顏色
        vectorcolorTab;
        for(int i=0;i(i,j);
            if(index==-1)
              watershedImage.at(i,j)=Vec3b(255,255,255);//圖像變白色
            else if(index<=0||index>compCount)
              watershedImage.at(i,j)=Vec3b(0,0,0);//圖像變黑色
            else
              watershedImage.at(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*)
{
  //處理鼠標不在窗口中的情況
  if(x<0||x>=g_srcImage.cols||y<0||y>=g_srcImage.rows)
    return;

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

  //鼠標左鍵按下并移動,繪制出白色線條
  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);//畫白線
    line(g_srcImage,prevPt,pt,Scalar::all(255),2,8,0);//畫白線
    prevPt=pt;
    imshow(WINDOW_NAME, g_srcImage);

  }
}

Opencv如何實現(xiàn)分水嶺算法
Opencv如何實現(xiàn)分水嶺算法Opencv如何實現(xiàn)分水嶺算法

Opencv技巧

(1)計算算法運行時間:

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

(2)改變圖像某點像素值:Mat類中的at方法對于獲取圖像矩陣某點的RGB值或者改變某點的值很方便,

對于單通道的圖像:image.at(i, j)
對于RGB通道的圖像:image.at(i, j)[0] 
         image.at(i, j)[1] 
         image.at(i, j)[2]

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

關于“Opencv如何實現(xiàn)分水嶺算法”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。


網(wǎng)站題目:Opencv如何實現(xiàn)分水嶺算法-創(chuàng)新互聯(lián)
文章來源:http://weahome.cn/article/dodhig.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部