1. 程式人生 > 實用技巧 >opencv學習(四)

opencv學習(四)

1、開閉操作

在前面的例子中我們使用Numpy構建了結構化元素,它是正方形的。
但有時我們需要構建一個橢圓形 / 圓形的核。為了實現這種要求,提供了OpenCV
函式cv2.getStructuringElement()。你只需要告訴他你需要的核的形狀和大小。
def open_demo(image):
    print(image.shape)
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow(
"binary",binary) kernel=cv.getStructuringElement(cv.MORPH_RECT,(5,5)) binary=cv.morphologyEx(binary,cv.MORPH_OPEN,kernel) cv.imshow("open_result",binary)

def close_demo(image):
    print(image.shape)
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow(
"binary",binary) kernel=cv.getStructuringElement(cv.MORPH_RECT,(15,15)) binary=cv.morphologyEx(binary,cv.MORPH_CLOSE,kernel) cv.imshow("close_result",binary)

頂帽操作:

def other_morphlpgy_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    kernel=cv.getStructuringElement(cv.MORPH_RECT,(15,15))
    dst
=cv.morphologyEx(gray,cv.MORPH_TOPHAT,kernel) cimage=np.array(gray.shape,np.uint8) cimage=127 cv.add(dst,cimage) cv.imshow("hot_tap",dst)

2、分水嶺運算

"""
分水嶺演算法原理:
  任何一副灰度影象都可以被看成拓撲平面,灰度值高的區域可以被看成是 山峰,灰度值低的區域可以被看成是山谷。
我們向每一個山谷中灌不同顏色的水。隨著水的位的升高,不同山谷的水就會相遇匯合,為了防止不同山谷的水 匯合,
我們需要在水匯合的地方構建起堤壩。不停的灌水,不停的構建堤壩知 道所有的山峰都被水淹沒。
我們構建好的堤壩就是對影象的分割。這就是分水嶺演算法的背後哲理
  但是這種方法通常都會得到過度分割的結果,這是由噪聲或者影象中其他不規律的因素造成的。
為了減少這種影響,OpenCV 採用了基於掩模的分水嶺演算法,在這種演算法中我們要設定那些山谷點會匯合,那些不會。
這是一種互動式的影象分割。我們要做的就是給我們已知的物件打上不同的標籤。
如果某個區域肯定是前景或物件,就使用某個顏色(或灰度值)標籤標記它。
如果某個區域肯定不是物件而是背景就使用另外一個顏色標籤標記。而剩下的不能確定是前景還是背景的區域就用 0 標記。
這就是我們的標籤。然後實施分水嶺演算法。
每一次灌水,我們的標籤就會被更新,當兩個不同顏色的標籤相遇時就構建堤壩,直到將所有山峰淹沒,
最後我們得到的邊界物件(堤壩)的值為 -1。

基於距離的分水嶺分割流程:
輸入影象->灰度->二值->距離變換->尋找種子->生成marker->分水嶺變換->輸出影象
"""
def water_shed(src):
    print(src.shape)
    blurred=cv.pyrMeanShiftFiltering(src,10,100)
    gray=cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
    ret,binary=cv.threshold(gray,0,255,cv.THRESH_OTSU|cv.THRESH_BINARY)
    cv.imshow("binary_image",binary)

#     morphology operation
    kernel=cv.getStructuringElement(cv.MORPH_RECT,(3,3))
    mb=cv.morphologyEx(binary,cv.MORPH_OPEN,kernel,iterations=2)
    sure_bg=cv.dilate(mb,kernel,iterations=3)
    cv.imshow("mor_opt",sure_bg)

距離變換

    # Finding sure foreground area
    # 距離變換的基本含義是計算一個影象中非零畫素點到最近的零畫素點的距離,
    # 也就是到零畫素點的最短距離
    # 個最常見的距離變換演算法就是通過連續的腐蝕操作來實現,腐蝕操作的停止條件是所有前景畫素都被完全腐蝕。
    # 這樣根據腐蝕的先後順序,我們就得到各個前景畫素點到前景中心畫素點的距離。
    # 根據各個畫素點的距離值,設定為不同的灰度值。這樣就完成了二值影象的距離變換
    # cv2.distanceTransform(src, distanceType, maskSize)
    # 第二個引數 0,1,2 分別表示 CV_DIST_L1, CV_DIST_L2 , CV_DIST_C
    dist=cv.distanceTransform(mb,cv.DIST_L2,3)
    dist_output=cv.normalize(dist,0,1.0,cv.NORM_MINMAX)
    cv.imshow("distance_t",dist_output*50)

尋找種子,生成marker

rec,surface=cv.threshold(dist,dist.max()*0.6,255,cv.THRESH_BINARY)
    cv.imshow("surface_bin",surface)

分水嶺計算

    dist=cv.distanceTransform(mb,cv.DIST_L2,3)
    dist_output=cv.normalize(dist,0,1.0,cv.NORM_MINMAX)
    cv.imshow("distance_t",dist_output*50)

    rec,surface=cv.threshold(dist,dist.max()*0.6,255,cv.THRESH_BINARY)
    cv.imshow("surface_bin",surface)

    # find unknown region
    surface_fg=np.uint8(surface)
    unknown=cv.subtract(sure_bg,surface_fg)

    ret,markers=cv.connectedComponents(surface_fg)
    print(ret)

#     watershed transform
    markers=markers+1
    markers[unknown==255]=0
    markers=cv.watershed(src,markers=markers)
    src[markers==-1]=[0,0,255]
    cv.imshow("result",src)