Python使用多线程操作tif影像和HBase数据库

news2024/11/17 11:28:03

本文介绍使用Python的多线程技术,提高happybase模块和gdal模块的效率,从tif格式的影像文件中读取数据,并将其存储到HBase数据库中。主要步骤包括:

  • 准备工作:安装Python环境,安装happybase模块和gdal模块,安装HBase数据库,并准备tif影像文件。
  • 读取tif影像数据:使用readTif函数读取tif影像数据集,并获取其宽度、高度、波段数、数据数组、仿射变换参数和投影信息。遍历tif影像文件所在的文件夹,获取tif影像文件的日期和分块信息。
  • 写入HBase数据库:创建一个happybase连接对象,并获取或创建一个happybase表对象。遍历每个分块,使用readTif函数读取每个分块的每个日期的每个波段的数据,并将其存储到一个三维的numpy数组中。遍历每个像素,将其对应的每个波段的每个日期的数据组合成一个字典,作为HBase表中的列值。使用分块编号、行号和列号拼接成一个字符串,作为HBase表中的行键。使用put方法将行键和列值写入HBase表中。关闭happybase连接对象。
  • 使用多线程技术:导入threading模块,创建一个信号量对象,用于限制线程的最大数量。遍历每个分块,使用信号量对象的acquire方法获取一个信号量,然后创建一个新的线程对象,并指定目标函数为load函数,以及传递分块编号、分块列表和日期列表作为参数。然后调用start方法启动该线程。在load函数中,在完成数据的读取和写入后,使用信号量对象的release方法释放一个信号量,并关闭happybase连接对象。记录程序运行的开始时间和结束时间,并计算程序运行的总时间。

一、环境准备

  • 安装Python环境,本文使用的是Anaconda3。
  • 安装happybase模块,可以使用pip或conda命令。例如:
pip install happybase
  • 安装gdal模块,可以使用pip或conda命令。例如:
conda install gdal
  • 启动分布式集群,hadoop以及hbase;启动thrift服务,可以使用hbase-daemon.sh脚本。例如:
hbase-daemon.sh start thrift

就可以使用happybase模块连接到thrift服务,并操作HBase数据库了 

  • 准备tif格式的影像文件,并放在一个文件夹中。本文使用的是Sentinel-2卫星的10个波段的影像数据,分为多个日期和多个分块。

二、定义读取tif影像数据的函数

  • 导入需要的模块,包括time、happybase、gdal、numpy、pandas、os、tqdm和threading。例如:
import time
import happybase
from osgeo import gdal
import numpy as np
import pandas as pd
import os
from tqdm import tqdm
import threading
  • 定义一个函数readTif,用于读取tif格式的影像数据集,并返回其宽度、高度、波段数、数据数组、仿射变换参数和投影信息。例如:
#  读取tif数据集
def readTif(fileName, xoff=0, yoff=0, data_width=0, data_height=0):
    dataset = gdal.Open(fileName)
    num_bands = dataset.RasterCount
    # print(num_bands)
    if dataset == None:
        print(fileName + "文件无法打开")
    #  栅格矩阵的列数
    width = dataset.RasterXSize
    #  栅格矩阵的行数
    height = dataset.RasterYSize
    #  波段数
    bands = dataset.RasterCount
    #  获取数据
    if (data_width == 0 and data_height == 0):
        data_width = width
        data_height = height
    data = dataset.ReadAsArray(xoff, yoff, data_width, data_height)
    #  获取仿射矩阵信息
    geotrans = dataset.GetGeoTransform()
    #  获取投影信息
    proj = dataset.GetProjection()
    return width, height, bands, data, geotrans, proj
  •  获取tif影像文件所在的文件夹路径,并遍历该文件夹下所有以.tif为后缀名的文件。例如:
# 分块影像所在文件夹,不能有中文
tifDir = r"E:\pyimg\tif2csv\S2SR10mallband3tile"
tifs = [i for i in os.listdir(tifDir) if i.endswith(".tif")]
print("有 %s 个tif文件" % len(tifs))
  •  获取tif影像文件的日期和分块信息,并去重排序。例如:
# 获取目标文件数量,前缀相同的
bandlist=['B2','B3','B4','B5','B6','B7','B8','B8A','B11','B12']
datelist1 = []
fenkuailist1 = []
for i in tifs:
    datelist1.append(i[:-26])
    fenkuailist1.append(i[-25:-4])

datelist = list(set(datelist1))
datelist.sort(key=datelist1.index)
fenkuailist = list(set(fenkuailist1))
fenkuailist.sort(key=fenkuailist1.index)
print("有 %s 个日期" % len(datelist))
print("datelist" , datelist)
print("每个日期 %s 个块" % len(fenkuailist))
print("fenkuailist" , fenkuailist)

三、创建happybase连接和表对象

  • 创建一个happybase连接对象,并指定HBase数据库的IP地址。例如:
connection = happybase.Connection('192.168.1.100')
# # before first use:
connection.open()
  • 获取或创建一个happybase表对象,并指定表名和列族名。例如:
table = connection.table('rawdata')

四、定义写入HBase数据库的函数

  • 定义一个函数load,用于读取和写入一个分块的数据。该函数接受分块编号、分块列表和日期列表作为参数。该函数的主要步骤如下:

    • 打印当前分块的编号。
    • 初始化一个三维的numpy数组,用于存储该分块的所有波段和所有日期的数据。
    • 遍历每个日期,使用readTif函数读取该分块的每个日期的每个波段的数据,并将其存储到numpy数组中。
    • 打印写入中的提示。
    • 遍历每个像素,将其对应的每个波段的每个日期的数据组合成一个字典,作为HBase表中的列值。使用分块编号、行号和列号拼接成一个字符串,作为HBase表中的行键。使用put方法将行键和列值写入HBase表中。
    • 关闭happybase连接对象。
def load(kuai,fenkuailist,datelist):
        connection = happybase.Connection('192.168.1.100')
        # # before first use:
        connection.open()
        table = connection.table('rawdata')
        
        print("(%d/%d)块编号:"%(kuai+1,len(fenkuailist)),fenkuailist[kuai])
        # 初始化立方体
        img_file = tifDir + "\\" + datelist[0] + "-" + fenkuailist[kuai] + ".tif"
        im_width, im_height, im_bands, im_data, kuai_im_geotrans, kuai_im_proj = readTif(img_file)

        tmpttt = np.empty((im_bands, im_width * im_height, len(datelist)))
    # print("波段 %s 个" % im_bands)
    # print("行列数", im_width, im_height)
        for shijian in range(len(datelist)):
        #  图像
            img_file = tifDir + "\\" + datelist[shijian] + "-" + fenkuailist[kuai] + ".tif"
            # print(img_file)
            im_width, im_height, im_bands, im_data, im_geotrans, im_proj = readTif(img_file)
            kuai_im_geotrans = im_geotrans
            kuai_im_proj=im_proj

            for j in range(im_bands):
                tmpttt[j, :, shijian] = im_data[j].flatten(order='C')
        print("写入中...")
        for index in tqdm(range(im_width * im_height)):
            dt={}
            for ban in range(im_bands):
                d1=zip(map(lambda  x:"f1:"+x+bandlist[ban],datelist),tmpttt[ban, index, :].astype(str))
            # Converting zip object to dict using dict() contructor.
                dt.update(d1)
            key=str(kuai%3)+fenkuailist[kuai][6:10]+fenkuailist[kuai][-4:]+str(index)
            table.put(key, dt)  # 提交数据,0001代表行键,写入的数据要使用字典形式表示
        connection.close()  # 关闭传输

五、使用多线程技术

  • 导入threading模块,该模块提供了多线程的支持,可以创建和管理线程,以及实现线程间的同步和通信。
  • 使用time模块的perf_counter函数,记录程序运行的开始时间。例如:
# #计时开始
start = time.perf_counter()
  • 使用threading模块的Semaphore类,创建一个信号量对象,用于限制线程的最大数量。信号量对象有一个内部计数器,每当一个线程调用acquire方法时,计数器减一,每当一个线程调用release方法时,计数器加一。如果计数器为零,那么acquire方法将阻塞,直到其他线程调用release方法。例如:
sem=threading.Semaphore(5) #限制线程的最大数量为5
  • 遍历每个分块,使用sem对象的acquire方法获取一个信号量,然后使用threading模块的Thread类,创建一个新的线程对象,并指定目标函数为load函数,以及传递分块编号、分块列表和日期列表作为参数。然后调用start方法启动该线程。例如:
for kuai in range(30,72):
    sem.acquire()
    threading.Thread(target = load, args = (kuai,fenkuailist,datelist)).start()
  • 在load函数中,在完成数据的读取和写入后,使用sem对象的release方法释放一个信号量,并关闭happybase连接对象。例如:
def load(kuai,fenkuailist,datelist):
        connection = happybase.Connection('192.168.1.100')
        # # before first use:
        connection.open()
        table = connection.table('rawdata')
        
        print("(%d/%d)块编号:"%(kuai+1,len(fenkuailist)),fenkuailist[kuai])
        # 初始化立方体
        img_file = tifDir + "\\" + datelist[0] + "-" + fenkuailist[kuai] + ".tif"
        im_width, im_height, im_bands, im_data, kuai_im_geotrans, kuai_im_proj = readTif(img_file)

        tmpttt = np.empty((im_bands, im_width * im_height, len(datelist)))
    # print("波段 %s 个" % im_bands)
    # print("行列数", im_width, im_height)
        for shijian in range(len(datelist)):
        #  图像
            img_file = tifDir + "\\" + datelist[shijian] + "-" + fenkuailist[kuai] + ".tif"
            # print(img_file)
            im_width, im_height, im_bands, im_data, im_geotrans, im_proj = readTif(img_file)
            kuai_im_geotrans = im_geotrans
            kuai_im_proj=im_proj

            for j in range(im_bands):
                tmpttt[j, :, shijian] = im_data[j].flatten(order='C')
        print("写入中...")
        for index in tqdm(range(im_width * im_height)):
            dt={}
            for ban in range(im_bands):
                d1=zip(map(lambda  x:"f1:"+x+bandlist[ban],datelist),tmpttt[ban, index, :].astype(str))
            # Converting zip object to dict using dict() contructor.
                dt.update(d1)
            key=str(kuai%3)+fenkuailist[kuai][6:10]+fenkuailist[kuai][-4:]+str(index)
            table.put(key, dt)  # 提交数据,0001代表行键,写入的数据要使用字典形式表示
        connection.close()  # 关闭传输
        sem.release()
  • 使用time模块的perf_counter函数,记录程序运行的结束时间,并计算程序运行的总时间。例如:
# #计时结束
delta = time.perf_counter()-start
print("程序运行的时间是:{}秒".format(delta))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/655011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows安装jdk1.8

1.下载jdk8 https://www.oracle.com/java/technologies/downloads/#java8-windows 百度网盘: 链接: https://pan.baidu.com/s/1qtVZ3Rsa1_n9XsFcXj07rA 提取码: yhwc 2.双击以后进行JDK的安装 操作前先在D盘保存java文件夹,里面新建jdk1.8.0_241文件…

AntDB 替换某省电信大数据平台的案例分享

亚信自研分布式数据库AntDB落地某省电信的案例分享 整体介绍 某省电信大数据分析平台,需要对BSS的三户、订单、实例等近10TB级的数据进行快速分析统计,每次分析的数据量最高达到5亿级别,同时需要向其它厂商开放这种实时的数据分析能力&…

Java-API简析_java.util.Currency类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://blog.csdn.net/m0_69908381/article/details/131255544 出自【进步*于辰的博客】 其实我的【Java-API】专栏内的博文对大家来说意义是不大的。…

对象实例化空指针处理

1 问题 如何解决对象实例化空指针异常? 2 方法 首先创建一个package包,将其Menu类及相关代码放入其中,并在该package包下创建另一个类MenuItem,然后通过构造函数,写入需要运行的对象信息,最后在Menu类中用n…

leetcode 151. 反转字符串中的单词

2023.6.14 这道题全面考察了字符串的一些操作,这里我的思路是: 先对字符串进行空格去除操作,这里要注意一个细节:先用for循环去除连续空格,再用if判断开头和结尾的空格。再对没有异常空格的s 做一个反转操作。再对每一…

计算机网络基础知识(九)—— 什么是TelnetS?Telnet Over TLS

文章目录 01 | TelnetS02 | OpenSSL03 | 实现思路服务器处理流程客户端处理流程 04 | 代码实现服务端代码客户端代码编译过程 & 执行结果 前面学习了什么是HTTPS协议,了解了HTTPS的工作原理以及具体的工作流程,了解了HTTP协议和HTTPS协议之间的区别。…

SSM框架搭建

SSM环境搭建 1 IDE的话,我用的MyEcplise,如果用Ecplise的话,需要自行配置服务器。 首先,建一个Dynamic工程,需要注意的是一定要勾选上web.xml。 将Spring框架包、jstl包、standard包、common-logging包、aopallian…

系列十三、MongoDB聚合查询

一、概述 MongoDB聚合框架(Aggregation Framework)是一个计算框架,它可以: ①:作用在一个或者几个集合上; ②:对集合中的数据进行一系列的运算; ③:将这些数据转化为期望的形式; 从效果而言…

AIGC技术研究与应用 ---- 下一代人工智能:新范式!新生产力!(5 - AIGC 未来展望)

文章大纲 不可避免的职业替代AI 对人类思维的影响AIGC 的风险人工智能对齐 -- 价值学习 鲁棒适应参考文献与学习路径GPT 系列模型解析前序文章模型进化券商研报陆奇演讲多模态据预测,未来五年10%-30%的图片内容由AI参与生成,考虑到下一代互联网对内容需求的迅速提升,2030年A…

计算机网络管理 实验4(一) SNMP报文分析之验证SNMP协议的工作过程以及分析SNMP数据单元的格式

⬜⬜⬜ 🐰🟧🟨🟩🟦🟪(*^▽^*)欢迎光临 🟧🟨🟩🟦🟪🐰⬜⬜⬜ ✏️write in front✏️ 📝个人主页:陈丹宇jmu &am…

FPGA基础知识-门级建模

目录 学习目标 学习内容 1.门的类型 2.门延迟 学习时间 学习小结 学习目标 学习Verilog 提供的门级原语 理解门的实例引用、门的符号以及andor,bufnot类型的门的真值表 学习如何根据电路的逻辑图来生成verilog描述 讲述门级设计中的上升、下降和关断延迟 …

【论文解读系列】Blip-2:引导语言图像预训练具有冻结图像编码器和大型语言模型

Blip-2 BLIP-2: Bootstrapping Language-Image Pre-training with Frozen Image Encoders and Large Language Models BLIP-2:引导语言图像预训练具有冻结图像编码器和大型语言模型 (0) 总结&实测 总结:blip-2 最大的贡献在于,提出了…

跨境电商社交媒体:选择合适的平台

正如您在使用社交媒体的九种方法中了解到的那样,跨境电商优先考虑社交媒体营销可能会更有利可图。有数十个平台可供选择,每个平台都迎合了具有不同兴趣、特征和位置的独特受众。 那么您应该关注哪个社交媒体平台以及如何以最大效率工作? 目…

【Vue全家桶高仿小米商城】——(三)VueCli4.0安装和使用

文章目录 第三章:VueCli4.0安装和使用一、VueCli4.0安装:二、创建Vue项目方式一 使用脚本搭建方式二 使用UI界面搭建 三、安装依赖方式一 Vue脚手架图形界面安装方式二、命令行安装 四、Vue DevTools安装使用两种安装方式: 第三章&#xff1a…

Linux权限解析

一、Linux用户分类 Linux下有两种用户:超级用户(root)、普通用户 超级用户:可以再linux系统下做任何事情,不受限制 普通用户:在linux下做有限的事情。 超级用户的命令提示符是“#”,普通用户的…

6.6面向对象继承

2. 面向对象特征二:继承(Inheritance) 2.1 继承的概述 说到继承我们会想到什么 在Java面向对象程序设计中的继承,多个类中存在相同属性和行为时,将这些相同的内容抽取到单独一个类(父类)中,然后所有的类继…

【备战秋招】每日一题:4月15日美团春招第二题:题面+题目思路 + C++/python/js/Go/java带注释

为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第二题-分糖果 在线评测链接:P1236 题目内容 某天,塔子哥去商店买了两种不同口味的糖果,分别买了 a 个和 b 个。当他回到家时,他发现他…

IDE/以glog为例实践CMake-Gui工具使用

文章目录 概述构建glog编译glog.sln解决方案glog的配置项BUILD_SHARED_LIBSBUILD_TESTINGCMAKE_CONFIGURATION_TYPESCMAKE_INSTALL_PREFIXWITH_GTESTGTest_DIRWITH_GFLAGSgflag_DIRPRINT_UNSYMBOLIZED_STACK_TRACESWITH_SYMBOLIZEWITH_FUZZINGWITH_THREADSWITH_TLSWITH_GMOCKWI…

3分钟了解如何做好项目管理和协作

目录 介绍 什么是项目管理 项目管理三要素 时间 成本 质量 项目启动阶段项目启动负责人要了解四个问题 项目规划阶段 任务分解->任务优先级安排->计划呈现->风险控制 快速呈现项目工作计划 项目启动:信息同步任务分工高效 项目跟踪&#xff1a…

实战:用docker-compose容器化springboot项目

文章目录 前言技术积累docker-compose定义docker-compose文件参数docker-compose命令 实战演示1、创建挂载路径2、编写docker-compose.yml3、启动并管理容器 写在最后 前言 前面我们学习和实战了用dockerfile构建镜像,通过镜像可以任意在docker环境容器化部署项目。…