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

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

python手撕分水嶺算法-創(chuàng)新互聯(lián)

python手撕分水嶺算法 1 分水嶺算法實(shí)現(xiàn)

主要思路就是:

創(chuàng)新互聯(lián)基于成都重慶香港及美國(guó)等地區(qū)分布式IDC機(jī)房數(shù)據(jù)中心構(gòu)建的電信大帶寬,聯(lián)通大帶寬,移動(dòng)大帶寬,多線BGP大帶寬租用,是為眾多客戶提供專業(yè)成都電信服務(wù)器托管報(bào)價(jià),主機(jī)托管價(jià)格性價(jià)比高,為金融證券行業(yè)服務(wù)器托管,ai人工智能服務(wù)器托管提供bgp線路100M獨(dú)享,G口帶寬及機(jī)柜租用的專業(yè)成都idc公司。
  • 利用一個(gè)優(yōu)先隊(duì)列與有序隊(duì)列(有序隊(duì)列其實(shí)可以不用)。優(yōu)先隊(duì)列是按像素的灰度值排列的,灰度值低的先被淹。
  • 通過(guò)統(tǒng)計(jì)像素的附近的點(diǎn)的標(biāo)記種類個(gè)數(shù)來(lái)確認(rèn)當(dāng)前像素點(diǎn)的標(biāo)記,并把該像素的四鄰域入隊(duì)。
  • 注意要使用梯度圖像,這樣使得各個(gè)部分蔓延的速度一樣。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
import plotly.express as px
from queue import Queue,PriorityQueue
import sys

class WATERSHED:
    def __init__(self,img,markers):
        if img.ndim!=2:
            raise ValueError("請(qǐng)輸入灰度圖")
        self.img = img
        # 求圖像梯度幅值
        self.gradient()
        self.markers = markers.astype(np.int32)
        self.img_highest = np.max(self.img)
        self.img_lowest = np.min(self.img)
        self.WSHED = -1# 分水嶺
        self.IN_QUEUE = -2#已入隊(duì),但未賦予標(biāo)記
        # 根據(jù)梯度幅值圖的灰度大最小值創(chuàng)建有序隊(duì)列
        self.ordered_queue = [[] for _ in range(self.img_highest-self.img_lowest+1)] 
    def gradient(self):
        # self.img = cv2.Canny(self.img,80,150)
        d_x= cv2.Sobel(self.img,cv2.CV_64F,1,0,ksize=3)
        d_y= cv2.Sobel(self.img,cv2.CV_64F,0,1,ksize=3)
        value = cv2.magnitude(d_x,d_y)
        self.img = cv2.convertScaleAbs(value)
    def ordered_queue_push(self,i,j):
        gray_leve = self.img[i][j]
        self.ordered_queue[gray_leve-self.img_lowest].append([i,j])
        self.markers[i][j] = self.IN_QUEUE
    def PriorityQueue_push(self,water_stage):
        # 將等于水位高度的像素點(diǎn)全部入優(yōu)先隊(duì)列
        for pix_coord in self.ordered_queue[water_stage-self.img_lowest]:
            self.wait_water_queue.put((water_stage,pix_coord))
    def wait_water_queue_push(self,x,y):
        self.wait_water_queue.put((self.img[x][y],[x,y]))
        self.markers[x][y] = self.IN_QUEUE
    def get_label(self,pix_coord:list,water_stage):
        x,y = pix_coord
        neighbour_pix_values = {}
        for i in [-1,0,1]:
            for j in [-1,0,1]:
                pix_x,pix_y = x+i,y+j
                if pix_x<0 or pix_y<0 or pix_x >=self.img.shape[0] \
                or pix_y >=self.img.shape[1] :
                    continue
                # 必須以四鄰域搜索,八鄰域會(huì)越過(guò)邊界
                if abs(i+j)==1:
                    if neighbour_pix_values.get(self.markers[pix_x][pix_y])!=None:
                        neighbour_pix_values[self.markers[pix_x][pix_y]]+=1
                    else:
                        neighbour_pix_values[self.markers[pix_x][pix_y]]=1
                    if self.markers[pix_x][pix_y]==0:#不在隊(duì)列且無(wú)標(biāo)簽
                        if self.img[pix_x][pix_y]<=water_stage:
                            #低于水位,入優(yōu)先隊(duì)列
                            self.wait_water_queue_push(pix_x,pix_y)
                        else:
                            #高于水位,還淹不到
                            self.ordered_queue_push(pix_x,pix_y)
        
        pix_values = list(neighbour_pix_values)
        #去掉分水嶺、入隊(duì)標(biāo)記和未標(biāo)記區(qū)域值
        pix_values = [value for value in pix_values \
            if value>0 and value!=self.IN_QUEUE]

        if len(pix_values)==1:           
            self.markers[x][y]=pix_values[0]
        else :
            self.markers[x][y]=self.WSHED            
    def run(self):
        
        for i in range(self.img.shape[0]):
            for j in range(self.img.shape[1]):
                #已標(biāo)記區(qū)域全部入隊(duì)
                if self.markers[i][j] >0:
                    gray_leve = self.img[i][j]
                    self.ordered_queue[gray_leve-self.img_lowest].append([i,j])
                           
        for water_stage in range(self.img_lowest,self.img_highest+1):
            sys.stdout.write("水位高度{}".format(water_stage))
            sys.stdout.flush()
            self.wait_water_queue = PriorityQueue()
            #將水位為water_stage的全部入優(yōu)先隊(duì)列
            self.PriorityQueue_push(water_stage)
            #每輪循環(huán)結(jié)束小于等于water_stage的像素值都得清空
            while self.wait_water_queue.qsize() >0:
                pix_coord = self.wait_water_queue.get()[1]
                self.get_label(pix_coord,water_stage)
            # 動(dòng)畫
            plt.clf()
            plt.imshow(self.markers)
            plt.pause(0.001)
        return self.markers
2 獲取初始標(biāo)記

如果如opencv官方例程那樣,用距離變換來(lái)確認(rèn)標(biāo)記,非常容易過(guò)分割,所以我們可以通過(guò)手動(dòng)進(jìn)行標(biāo)記。
可以使用opencv的鼠標(biāo)事件實(shí)現(xiàn)標(biāo)記。

import cv2
import numpy as np

class draw_markers:
    def __init__(self,img,resize_rate:int=1):
        if img.ndim == 2:
            self.img = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
        else:
            self.img = img
        self. resize_rate = resize_rate
        
        self.r,self.w = self.img.shape[:2]
        self.markers = np.zeros_like(self.img)
        # 放大
        self.img = cv2.resize(self.img,(self.r*resize_rate,self.w*resize_rate))
        self.markers = cv2.resize(self.markers,(self.r*resize_rate,self.w*resize_rate))
        
        self.cls_num =0
        #標(biāo)記顏色列表
        self.color_list = [(255,0,0),(0,255,0),(0,0,255),(255,255,0),(255,0,255),(0,255,255)]
        self.drawing = False
    def mark(self,event, x, y,flags, param):
        if event==cv2.EVENT_LBUTTONDOWN:
            self.drawing = True
        if event == cv2.EVENT_LBUTTONUP:
            self.drawing = False
        if self.drawing:
            cv2.circle(self.img,(x,y),radius=1,color=self.color_list[self.cls_num],thickness=-1)
            cv2.circle(self.markers,(x,y),radius=1,color=self.color_list[self.cls_num],thickness=-1)
    def draw(self):
        cv2.namedWindow('image')
        cv2.setMouseCallback('image',self.mark)

        while True:
            cv2.imshow('image',self.img)
            k = cv2.waitKey(1) & 0xFF
            if k==ord('c'):
                self.cls_num +=1
                print("第{}類".format(self.cls_num+1))
            if k==27:
                break
        cv2.destroyAllWindows()
        result = cv2.cvtColor(self.markers,cv2.COLOR_BGR2GRAY)
        #不能用插值,會(huì)改變標(biāo)簽值
        result = result[::self.resize_rate,::self.resize_rate]
        cv2.imwrite('./markers.png',self.img)
        return result
3 主函數(shù)
  • 首先獲得標(biāo)記
  • 開運(yùn)算
  • 分水嶺

要想分割的好,要避免不同區(qū)域的連通,相同區(qū)域的分裂。銳化和高斯模糊感覺(jué)用了效果不好。

img = cv2.imread('test.png',0)
#標(biāo)記圖像
DM = draw_markers(img,1)
markers = DM.draw()
#開運(yùn)算
kernel = np.ones((5,5),dtype=np.uint8)
img = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel,iterations=1)
# img = cv2.erode(img,kernel=np.ones((5,5)),iterations=2)
# img = cv2.GaussianBlur(img,(5,5),sigmaX=0)

# #銳化
# kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]], dtype=np.float32)
# imgLaplacian = cv2.filter2D(img, cv2.CV_32F, kernel)
# sharp =np.float32(img)
# imgResult = sharp - imgLaplacian
# imgResult = np.clip(imgResult,0,255)
# imgResult = np.uint8(imgResult)
#開始分水嶺算法
WSHED= watershed.WATERSHED(img,markers)
result = WSHED.run()
#將所有的分水嶺轉(zhuǎn)為255
result[result==-1]==255
result = result.astype(np.uint8)
imshow(result,'result.png')
4 實(shí)驗(yàn)結(jié)果 4.1 標(biāo)記圖像

在這里插入圖片描述

4.2 分割結(jié)果

對(duì)比opencv官方例程,過(guò)分割現(xiàn)象減少。

在這里插入圖片描述
在這里插入圖片描述
opencv例程結(jié)果如下:
在這里插入圖片描述

5 參考文獻(xiàn)

COLOR IMAGE SEGMENTATION
Image Segmentation with Distance Transform and Watershed Algorithm
OpenCV cv::watershed 分水嶺算法論文解讀以及numpy實(shí)現(xiàn)

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)站標(biāo)題:python手撕分水嶺算法-創(chuàng)新互聯(lián)
分享路徑:http://weahome.cn/article/gedps.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部