python實現遙感圖像閾值分割


1.閾值分割

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from osgeo import gdal

GRAY_SCALE = 256

def tif_jpg(rasterfile):
    in_ds = gdal.Open(rasterfile)  # 打開樣本文件
    xsize = in_ds.RasterXSize  # 獲取行列數
    ysize = in_ds.RasterYSize
    bands = in_ds.RasterCount
    block_data = in_ds.ReadAsArray(0, 0, xsize, ysize).astype(np.float32)
    B = block_data[0, :, :]

    G = block_data[ 1,:, :]
    R = block_data[2,:, :]
    R1 =  (R/np.max(R)*255).astype(np.int16)
    G1 = (G / np.max(G) * 255).astype(np.int16)
    B1 = (B / np.max(B) * 255).astype(np.int16)
    data2 = cv2.merge([R1,G1,B1])
    return data2


def write_tiff(path,image_gray,out):
    in_ds = gdal.Open(path)  # 打開樣本文件
    xsize = in_ds.RasterXSize  # 獲取行列數
    ysize = in_ds.RasterYSize
    bands = in_ds.RasterCount
    geotransform = in_ds.GetGeoTransform()
    projection = in_ds.GetProjectionRef()

    driver = gdal.GetDriverByName('GTiff')
    outfile = out + "\\" + os.path.basename(path).split(".tif")[0] + "_mask.tif"  # 對輸出文件命名
    out_dataset = driver.Create(outfile, xsize, ysize, 1, gdal.GDT_Float32)  # 創建一個一波段的數據框架
    out_band1 = out_dataset.GetRasterBand(1)
    out_band1.WriteArray(image_gray)

    out_dataset.SetGeoTransform(geotransform)  # 寫入仿射變換
    out_dataset.SetProjection(projection)
if __name__ == '__main__':
    path = r"D:\data\實驗數據\3\3.tif"
    out = r"D:\data\實驗結果"

    #設置閾值
    thresh=40

    #tif轉jpg並灰度化
    img = tif_jpg(path).astype(np.uint8)
    image_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    #高斯濾波
    img_blur = cv2.GaussianBlur(image_gray , (5, 5), 5)
    # 閾值提取
    img_blur[img_blur > thresh] = 255
    img_blur[img_blur<=  thresh] =1
    write_tiff(path, img_blur, out)

2.直方圖雙峰法閾值分割

import os
from osgeo import gdal
import numpy as np
import cv2
GRAY_SCALE = 256

def tif_jpg(rasterfile):
    in_ds = gdal.Open(rasterfile)  # 打開樣本文件
    xsize = in_ds.RasterXSize  # 獲取行列數
    ysize = in_ds.RasterYSize
    bands = in_ds.RasterCount
    block_data = in_ds.ReadAsArray(0, 0, xsize, ysize).astype(np.float32)
    B = block_data[0, :, :]

    G = block_data[ 1,:, :]
    R = block_data[2,:, :]
    R1 =  (R/np.max(R)*255)
    G1 = (G / np.max(G) * 255)
    B1 = (B / np.max(B) * 255)
    data2 = cv2.merge([R1,G1,B1]).astype(np.int16)
    return data2


def calcGrayHist(image):
    '''
    統計像素值
    :param image:
    :return:
    '''
    # 灰度圖像的高,寬
    rows, cols = image.shape
    # 存儲灰度直方圖
    grayHist = np.zeros([256], np.uint64)
    for r in range(rows):
        for c in range(cols):
            grayHist[image[r][c]] += 1
    return grayHist

#直方圖全局閾值
def threshTwoPeaks(image):

    # 計算灰度直方圖
    histogram = calcGrayHist(image)

    # 找到灰度直方圖的最大峰值對應的灰度值
    maxLoc = np.where(histogram == np.max(histogram))
    firstPeak = maxLoc[0][0]

    # 尋找灰度直方圖的第二個峰值對應的灰度值
    measureDists = np.zeros([256], np.float32)
    for k in range(256):
        measureDists[k] = pow(k - firstPeak, 3) * histogram[k]#GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
    maxLoc2 = np.where(measureDists == np.max(measureDists))
    secondPeak = maxLoc2[0][0]

    if firstPeak > secondPeak:
        temp = histogram[int(secondPeak): int(firstPeak)]
        minLoc = np.where(temp == np.min(temp))
        thresh = secondPeak + minLoc[0][0]+ 1
    else:
        temp = histogram[int(firstPeak): int(secondPeak)]
        minLoc = np.where(temp == np.min(temp))
        thresh = firstPeak + minLoc[0][0]
    img = image.copy()
    img[img >= thresh] = 255
    img[img < thresh] = 0
    print("firstPeak:",firstPeak,",secondPeak:",secondPeak,",thresh:",thresh)
    return img

def write_tiff(path,image_gray,out):
    in_ds = gdal.Open(path)  # 打開樣本文件
    xsize = in_ds.RasterXSize  # 獲取行列數
    ysize = in_ds.RasterYSize
    bands = in_ds.RasterCount
    geotransform = in_ds.GetGeoTransform()
    projection = in_ds.GetProjectionRef()
    driver = gdal.GetDriverByName('GTiff')
    outfile = out + "\\" + os.path.basename(path).split(".tif")[0] + "_mask.tif"  # 對輸出文件命名
    out_dataset = driver.Create(outfile, xsize, ysize, 1, gdal.GDT_Float32)  # 創建一個一波段的數據框架
    out_band1 = out_dataset.GetRasterBand(1)
    out_band1.WriteArray(image_gray)


    out_dataset.SetGeoTransform(geotransform)  # 寫入仿射變換
    out_dataset.SetProjection(projection)
    return outfile

if __name__ == '__main__':
    mask = r"F:\algorithm\算法練習\3_cut.tif"
    out = r"F:\algorithm\算法練習"
    img=tif_jpg(mask).astype(np.uint8)
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    seg_data = threshTwoPeaks(gray_img)
    write_tiff(mask, seg_data , out)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM