Tiff图像处理1_Python

读、写、显示Tiff图像

最近在处理Landsat的遥感影像。.tif格式的图像,与之前接触的.jpg,.png不太一样,在读写上面有更多的要求和规范。学习了好久,尤其是在显示上。由于之前并不是很懂数据类型的转换(后续已解决),在自己的电脑上怎么样都点不开,会显示:
在这里插入图片描述
所以经常因为,看不到图像长什么样,所以会陷入一种麻烦,不够直接,每次看还得打开ArcGIS等软件才能,太难顶了。再加上懒得整理笔记和做过的东西,走过的坑,就发奋来记录一下吧。
这一部分现在看来还是比较简单的,方便以后自己查阅,所以基本上写了很多乱七八糟的注释,就直接放代码了。

import os
import numpy as np
from PIL import Image
from osgeo import gdal
import cv2
# 不一定所有库都用上了,只是方便
# 读取tif图像的数据(只是读取数据,不是显示)
def readTiff(img_path):
    dataset = gdal.Open(img_path)
    if dataset == None:
        print(img_path + "文件无法打开")
        return
    im_width = dataset.RasterXSize  # 栅格矩阵的列数
    im_height = dataset.RasterYSize  # 栅格矩阵的行数
    im_bands = dataset.RasterCount  # 波段数
    band1 = dataset.GetRasterBand(1)
    # print(im_bands)
    # print('Band Type=', gdal.GetDataTypeName(band1.DataType))  # 输出band的类型
    im_data = dataset.ReadAsArray(0, 0, im_width, im_height)  # 获取数据,将数据写成数组,对应栅格矩阵,前两个参数是偏移量
    im_geotrans = dataset.GetGeoTransform()  # 获取仿射矩阵信息
    im_proj = dataset.GetProjection()  # 获取地图投影信息
    # print(im_data.shape)
    return im_data, im_geotrans, im_proj
# 将数据写成tif格式图像保存
def writeTiff(im_data, im_geotrans, im_proj, img_path):
    # 判断数据类型
    if 'int8' in im_data.dtype.name:
        datatype = gdal.GDT_Byte
    elif 'int16' in im_data.dtype.name:
        datatype = gdal.GDT_UInt16
    else:
        datatype = gdal.GDT_Float32
    # 判断数据的波段数
    if len(im_data.shape) == 3:  # 三个参数,波段数,H,W
        im_bands, im_height, im_width = im_data.shape
    # elif len(im_data.shape) == 2:  # 两个参数,一般只有灰度图,band为1,不显示,只有H,W,相当于直接是二维矩阵了
    #     im_data = np.array([im_data])
    else:
        im_bands, (im_height, im_width) = 1, im_data.shape  # 同上,没有band值的返回值,就手动给band赋值
    # 创建tif文件
    driver = gdal.GetDriverByName("GTiff") # 读取某一类型的数据,需要先载入数据驱动,初始化一个对象
    dataset = driver.Create(img_path, im_width, im_height, im_bands, datatype)  # 在路径处创建空文件,并确定开辟多大内存;每个像素都有一个对应的值,这个值得类型用数据类型指定。这里的数据类型是gdal数据类型。
    # 设置头文件信息
    if (dataset != None):
        dataset.SetGeoTransform(im_geotrans)  # 写入仿射变换参数
        dataset.SetProjection(im_proj)  # 写入投影
    # 写入数据体
    if im_bands == 1:
        dataset.GetRasterBand(1).WriteArray(im_data)  # 单通道无需循环赋值
    else:
        for i in range(im_bands):  # i从0开始,数组是从0开始,但是获取波段是从1开始
            dataset.GetRasterBand(i + 1).WriteArray(im_data[i])  # 写入数组数据
    # 释放内存空间
    del dataset
# 使用CV2,显示tif图像
def showTiff(img_path):
    img = cv2.imread(img_path,4)
    # 第二个参数是通道数和位深的参数,
    # IMREAD_UNCHANGED = -1  # 不进行转化,比如保存为了16位的图片,读取出来仍然为16位。
    # IMREAD_GRAYSCALE = 0  # 进行转化为灰度图,比如保存为了16位的图片,读取出来为8位,类型为CV_8UC1。
    # IMREAD_COLOR = 1  # 进行转化为RGB三通道图像,图像深度转为8位
    # IMREAD_ANYDEPTH = 2  # 保持图像深度不变,进行转化为灰度图。
    # IMREAD_ANYCOLOR = 4  # 若图像通道数小于等于3,则保持原通道数不变;若通道数大于3则只取取前三个通道。图像深度转为8位
    # print(img)  # 输出图像的数据
    # print(img.shape)  # 输出图像的三维
    # print(img.dtype)  # 输出图像的编码类型
    # print(img.min())  # 输出图像的最小值
    # print(img.max())  # 输出图像的最大值
    # 创建窗口并显示图像
    cv2.namedWindow("Image")  # 创建一个窗口
    cv2.imshow("Image", img)  # 显示图像
    cv2.waitKey(0)  # 设置显示图像的延迟
    # 释放窗口
    cv2.destroyAllWindows()

使用的GDAL版本是:
GDAL-3.1.3-cp38-cp38-win_amd64.whl
在实验室的电脑上好像安装别的版本,cmd里用pip安装会报错,pycharm里install也会报错(command error),应该是要找一个最符合的才行。下载GDAL的whl链接:
https://www.lfd.uci.edu/~gohlke/pythonlibs/#gdal

最初接触tif图像,带地理坐标和投影信息,不是很懂。以为打不开的原因是有地理坐标和投影信息等其他参数,所以写代码去show。但其实这个show的条件是,图像本身就是能打开的。我之前使用的GID数据集,那个本来就是能直接点开的,所以用这个代码没问题。后面找到了更好的办法,就没有测试这个show的代码是否也能适用,大概率是不适用的。图像能不能在计算机中直接显示,取决于的是图像本身的数据类型,如果是uint8的类型,就是能直接双击打开的,其他比如float32或者别的,可能就会出现打不开的提示。

你可能感兴趣的:(遥感,图像处理,python,tiff,图像处理,计算机视觉)