Python cmd命令行运行exe文件显示No module named ‘osgeo._gdal’

近期,在做一个水印系统,原本只应用opencv处理普通图像就好了,但老师要求还得能处理遥感瓦片数据,接下来就开始了一段痛苦的旅程,当然最后问题都解决了,现在就是做个总结。

1,处理遥感图像,必须要用GDAL!!

(1)如果只是查看8位遥感图像,可以只使用opencv,PIL或者Tiff库直接读取;

(2)如果只是查看16位遥感图像,可以先进行数据拉伸降到8位,然后使用opencv,PIL或者Tiff库直接读取;

def Tiff16to8bit(img_16):
    if np.max(img_16) - np.min(img_16) != 0:
        # img_nrm = (img_16 - np.min(img_16)) / (np.max(img_16) - np.min(img_16)) #计算灰度范围,归一化
        img_nrm = normalization(img_16)
        img_8 = np.uint8(255 * img_nrm)
    return img_8

但这样显示的图像会与使用envi显示的有所差别。(当然是以envi为准!)

注:这是以前的草稿,现在说明一下,16位降8位,理论上正确的做法是找到当前波段的最大值和最小值,以二者之差作为整个区间,计算当前像素所占比例,再以此比例乘以255,但是得到的结果还是会有较大的图像损失。还有的博客提到利用gdal.Translate来实现,我试了下,结果比自己按照原理写的效果要好一些,但这个涉及到很多参数,所以暂时没有深入研究。

(3)如果要对16位遥感图像的像素值进行处理,比如加水印,就一定要用gdal。遥感图像包含图像信息和地理信息,我们单取其图像信息进行一系列操作,最后再与地理信息结合,就得到了处理后的遥感图像。

读操作:

def readTif(fileName):
    dataset = gdal.Open(fileName)
    if dataset == None:
        print(fileName + "文件无法打开")
        return
    return dataset
    # im_width = dataset.RasterXSize #栅格矩阵的列数
    # im_height = dataset.RasterYSize #栅格矩阵的行数
    # im_bands = dataset.RasterCount #波段数
    # im_data = dataset.ReadAsArray(0,0,im_width,im_height)#获取数据
    # im_geotrans = dataset.GetGeoTransform()#获取仿射矩阵信息
    # im_proj = dataset.GetProjection()#获取投影信息
    # im_blueBand =  im_data[0,0:im_height,0:im_width]#获取蓝波段
    # im_greenBand = im_data[1,0:im_height,0:im_width]#获取绿波段
    # im_redBand =   im_data[2,0:im_height,0:im_width]#获取红波段
    # im_nirBand = im_data[3,0:im_height,0:im_width]#获取近红外波段

想返回哪个值就解开哪个值。

写操作:

def writeTiff(im_data, im_width, im_height, im_bands, im_geotrans, im_proj, 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:
        im_bands, im_height, im_width = im_data.shape
    else:
        im_bands, (im_height, im_width) = 1, im_data.shape
        # 创建文件
    driver = gdal.GetDriverByName("GTiff")
    dataset = driver.Create(path, im_width, im_height, im_bands, datatype)
    if dataset is not None:
        dataset.SetGeoTransform(im_geotrans)  # 写入仿射变换参数
        dataset.SetProjection(im_proj)  # 写入投影
    for i in range(im_bands):
        dataset.GetRasterBand(i + 1).WriteArray(im_data[i])
    del dataset

要强调的一点是,程序不是死板的,有时候不用函数,而把其分解开,只取所需,会更有利于你实现运行效果,比如,我需要对某个通道进行操作而不是全部,这样在写操作时,明显就是后者的思想更方便。

2,进入正题,xx.py程序在pycharmde 终端中输入python xx.py可以正常运行,但打包后,cmd运行exe就显示缺失模块。 

原因在很多博客中都说的很清楚了,就是运行方式不同,导致路径搜索的方式不同。网上关于这个问题的所有帖子我几乎都看过了,方法也几乎都试过了,但对我都没有用。这里将几种方法罗列一下,也许某种对大家有用呢。

方法(1)在源程序中添加搜索路径

import sys
import os 
 curPath = os.path.abspath(os.path.dirname(__file__))
 rootPath = os.path.split(curPath)[0]
 sys.path.append(rootPath)

 curPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 sys.path.append(curPath)

等等类似的。

这里要强调的是,这部分一定要在源程序中,添加到显示缺失的库之前。比如我缺失的是osgeo._gdal,那么‘from osgeo import gdal’   就一定要在上面这部分程序的下面。

方法(2)修改spec文件。

在spec文件中

 在红框部分,添加缺失的库,比如我添加了hiddenimport=['osgeo','gdal','osgeo._gdal'],然后直接pyinstaller xx.spec。当然是有效果的,报错信息不在命令行中显示了,而是弹窗显示。

方法(3)在F:\Anaconda3\Lib\site-packages中,自己添加xx.pth文件。

这个方法与导入自定义库的方法一致。先新建一个.txt文件,里面的内容存放缺失的库的绝对路径

 然后另存的时候,类型选择*.*全部文件,只修改后缀为.pth即可。

当然,也是没效果啦。

方法(4)在环境变量中添加PYTHONPTH。

 或者设置USE_PATH_FOR_GDAL_PAYTHON=YES

 确实 还是不行。

方法(5)当时我已经熬到了晚上快3点,最后索性直接all in。

只要是相关的环境变量路径,添加就完事了。

 

 当时试了之后还是不行,扛不住了就关电脑睡了,第二天打开电脑不信邪 pyinstaller -F xx.py 再一次打包,再一次cmd运行,然后。。。然后就成功了。很玄学了可以说是。

以上全是本人亲身经历。其中滋味,苦不堪言,但成功的那一刻,还是开心的。极致的痛苦之后方见解脱后的幸福,人造多巴胺了属于是。希望这篇文章能帮助到大家啊~~

对了,多提一句,上述问题是去年遇到的问题,现在建议大家安装库都用anaconda,它会自动帮你找到适应你python版本的库的版本,这样程序中应该就不会出现找不到的库的情形了,至少对我而言,已经没有再遇到过这种问题了。

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值