0基础学习Mybatis系列数据库操作框架——Mysql的Geometry数据处理之WKT方案

news2024/10/7 7:31:08

大纲

  • 几何结构构建
    • 点集合
    • 线
    • 线集合
    • 面集合
    • 几何信息集合
  • TypeHandler
  • SQL操作
    • 写入操作
    • 读取操作
    • 完整XML
  • Mapper
  • 测试代码
  • 建表SQL
  • 总结
  • 代码
  • 参考资料

WKT全称是Well-Known Text。它是一种表达几何信息的字符串内容。比如点可以用WKT表示为POINT (3 3);线可以用WKT表示为LINESTRING (1 1, 2 2)。
Mysql数据库可以存储一些几何类型数据,比如点、线、多边形等。这在一些基于地理信息的服务上比较有用,比如在地图上的商店地理坐标(点),或者路径规划中的行进路线(线)等。
目前我使用的Mysql是8.4.0版本,它支持如下几何类型数据结构。

类型说明样例图例
POINT (3 3)在这里插入图片描述
点集合MULTIPOINT ((1 1), (2 2), (3 3))
线LINESTRING (1 1, 2 2)在这里插入图片描述
线集合MULTILINESTRING ((1 1, 2 2), (3 3, 4 4))
多边形POLYGON ((1 1, 2 2, 3 3, 1 1))在这里插入图片描述
多边形集合MULTIPOLYGON (((1 1, 2 2, 3 3, 1 1)), ((4 4, 5 5, 6 6, 4 4)))
多种几何类型集合GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (1 1, 2 2), POLYGON ((1 1, 2 2, 3 3, 1 1)))

一般我们会使用org.locationtech.jts的Geometry类来表达几何信息。

<dependency>
    <groupId>org.locationtech.jts</groupId>
    <artifactId>jts-core</artifactId>
    <version>1.19.0</version>
</dependency>

然后使用下面的方法构建各种结构

几何结构构建

GeometryFactory geometryFactory = new GeometryFactory();
Geometry geometry = geometryFactory.createPoint(new Coordinate(3, 3));

点集合

GeometryFactory geometryFactory = new GeometryFactory();
LineString lineString = geometryFactory
        .createLineString(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2) });

线

GeometryFactory geometryFactory = new GeometryFactory();
LineString lineString = geometryFactory
        .createLineString(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2) });

线集合

GeometryFactory geometryFactory = new GeometryFactory();
MultiLineString multiLineString = geometryFactory.createMultiLineString(new LineString[] {
        geometryFactory
                .createLineString(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2) }),
        geometryFactory
                .createLineString(new Coordinate[] { new Coordinate(3, 3), new Coordinate(4, 4) })
});

GeometryFactory geometryFactory = new GeometryFactory();
Polygon polygon = geometryFactory.createPolygon(new Coordinate[] { new Coordinate(1, 1),
 					new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(1, 1) });

面集合

GeometryFactory geometryFactory = new GeometryFactory();
MultiPolygon multiPolygon = geometryFactory.createMultiPolygon(new Polygon[] {
        geometryFactory.createPolygon(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2),
                new Coordinate(3, 3), new Coordinate(1, 1) }),
        geometryFactory.createPolygon(new Coordinate[] { new Coordinate(4, 4), new Coordinate(5, 5),
                new Coordinate(6, 6), new Coordinate(4, 4) })
});

几何信息集合

GeometryFactory geometryFactory = new GeometryFactory();
GeometryCollection geometryCollection = geometryFactory.createGeometryCollection(new Geometry[] {
        geometryFactory.createPoint(new Coordinate(1, 1)),
        geometryFactory.createLineString(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2) }),
        geometryFactory.createPolygon(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2),
                new Coordinate(3, 3), new Coordinate(1, 1) })
});

下面我们需要将这些结构保存到Mysql数据库中。
由于org.locationtech.jts.geom.Geometry和Mysql内部存储的Geometry不配,所以需要转换操作,于是就要引入typehandler。

TypeHandler

package org.example.typehandlers;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.PrecisionModel;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class GeometryTypeWKTHandler extends BaseTypeHandler<Geometry>  {
    private static GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING), 4326);

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType) throws SQLException {
        String str = serializeGeometry(parameter);
        ps.setString(i, str);;
    }

    @Override
    public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String str = rs.getString(columnName);
        try {
            return deserializeGeometry(str);
        } catch (ParseException e) {
            throw new SQLException(e);
        }
    }

    @Override
    public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String str = rs.getString(columnIndex);
        try {
            return deserializeGeometry(str);
        } catch (ParseException e) {
            throw new SQLException(e);
        }
    }

    @Override
    public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String str = cs.getString(columnIndex);
        try {
            return deserializeGeometry(str);
        } catch (ParseException e) {
            throw new SQLException(e);
        }
    }

    private static String serializeGeometry(Geometry geometry) {
        WKTWriter writer = new WKTWriter(2);
        return writer.write(geometry);
    }

    private static Geometry deserializeGeometry(String wkt) throws ParseException {
        return new WKTReader(factory).read(wkt);
    }

}

WKTWriter会将org.locationtech.jts.geom.Geometry转换为String,然后交由SQL语句处理;
WKTReader会将SQL语句读取出来的String转换为org.locationtech.jts.geom.Geometry对象。
在这里插入图片描述

SQL操作

在上图我们看到,TypeHandler主要使用String类型作为媒介来和SQL语句联系。那么SQL语句是如何把String转成Mysql的Geometry内部结构的呢?
这就需要引入ST_GeomFromText和ST_AsText。
ST_GeomFromText可以将WKT格式的几何信息转换为Mysql内部的Geometry结构。比如

ST_GeomFromText('MULTIPOINT (1 1, 2 2, 3 3)')

ST_AsText则可以将Mysql内部的Geometry结构转换为WKT格式的几何信息
在这里插入图片描述

在Mybatis的SQL XML中

写入操作

对org.locationtech.jts.geom.Geometry结构(即geometry字段)使用org.example.typehandlers.GeometryTypeWKTHandler处理成WTK(字符串)几何信息格式后,用ST_GeomFromText转换成Mysql内部的Geometry结构,然后存储。

    <insert id="insertOne" parameterType="org.example.model.GeometryData"  useGeneratedKeys="true" keyProperty="id">
        insert into geometry_data(id, geometry, update_time, create_time) values
        (#{id}, ST_GeomFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())
    </insert>

这儿需要注意的是ST_GeomFromText不是万能的。比如针对“几何信息集合”(GeometryCollection)则需要使用ST_GeomCollFromText来转换

    <insert id="insertGeometryCollection" parameterType="org.example.model.GeometryData"  useGeneratedKeys="true" keyProperty="id">
        insert into geometry_data(id, geometry, update_time, create_time) values
        (#{id}, ST_GeomCollFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())
    </insert>

读取操作

由于需要对geometry字段特殊处理,所以不能使用Select * From geometry_data,而需要把每个参数都写好。
ST_AsText会将Mysql的内部的Geometry结构转换成WKT格式(字符串)的几何信息,然后交由org.example.typehandlers.GeometryTypeWKTHandler转换成org.locationtech.jts.geom.Geometry结构。

    <resultMap id="GeometryDataResultMap" type="org.example.model.GeometryData">
        <result property="id" column="id"/>
        <result property="geometry" column="geometry" typeHandler="org.example.typehandlers.GeometryTypeWKTHandler" jdbcType="BLOB"/>
        <result property="updateTime" column="update_time"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <select id="findAll" resultMap="GeometryDataResultMap">
        select id, ST_AsText(geometry) AS geometry, update_time, create_time from geometry_data
    </select>

完整XML

<?xml version="1.0" encoding="UTF-8"?>
<!-- AllTypeMapper-1.xml -->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.GeometryDataWKTMapper">
    <resultMap id="GeometryDataResultMap" type="org.example.model.GeometryData">
        <result property="id" column="id"/>
        <result property="geometry" column="geometry" typeHandler="org.example.typehandlers.GeometryTypeWKTHandler" jdbcType="BLOB"/>
        <result property="updateTime" column="update_time"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <select id="findAll" resultMap="GeometryDataResultMap">
        select id, ST_AsText(geometry) AS geometry, update_time, create_time from geometry_data
    </select>

    <select id="find" resultMap="GeometryDataResultMap">
        select id, ST_AsText(geometry) AS geometry, update_time, create_time from geometry_data where id = #{id}
    </select>

    <insert id="insertOne" parameterType="org.example.model.GeometryData"  useGeneratedKeys="true" keyProperty="id">
        insert into geometry_data(id, geometry, update_time, create_time) values
        (#{id}, ST_GeomFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())
    </insert>

    <insert id="insertList" parameterType="list">
        insert into geometry_data(id, geometry, update_time, create_time) values
        <foreach item="item" collection="list" separator=",">
            (#{item.id}, ST_GeomFromText(#{item.geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())
        </foreach>
    </insert>

    <update id="updateOne" parameterType="org.example.model.GeometryData">
        update geometry_data set geometry = ST_GeomFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), update_time = now() where id = #{id} 
    </update>

    <insert id="insertGeometryCollection" parameterType="org.example.model.GeometryData"  useGeneratedKeys="true" keyProperty="id">
        insert into geometry_data(id, geometry, update_time, create_time) values
        (#{id}, ST_GeomCollFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())
    </insert>

</mapper>

Mapper

package org.example.mapper;

import java.util.List;

import org.example.model.GeometryData;

public interface GeometryDataWKTMapper {
    public List<GeometryData> findAll();
    public GeometryData find(Long id);
    public Long insertOne(GeometryData geometryData);
    public Long insertList(List<GeometryData> geometryDataList);
    public Long updateOne(GeometryData geometryData);
    public Long insertGeometryCollection(GeometryData geometryData);
} 

测试代码

package org.example;

import static org.junit.jupiter.api.Assertions.fail;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.example.mapper.GeometryDataWKTMapper;
import org.example.model.GeometryData;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.MultiLineString;
import org.locationtech.jts.geom.MultiPoint;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Polygon;

public class GeometryDataWKTTest {
    private static SqlSessionFactory sqlSF;

    @BeforeAll
    static void CreateSessionFactory() throws IOException {
        InputStream in = Resources.getResourceAsStream("mybatis/config/mybatis-config-geometry-wkt.xml");
        sqlSF = new SqlSessionFactoryBuilder().build(in);
    }

    @Test
    public void testFindAll() {
        List<GeometryData> all = null;
        try (SqlSession session = sqlSF.openSession()) {
            all = session.getMapper(GeometryDataWKTMapper.class).findAll();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        for (GeometryData a : Objects.requireNonNull(all)) {
            System.out.println(a.getGeometry());
        }
    }

    @Test
    public void testFind() {
        try (SqlSession session = sqlSF.openSession()) {
            GeometryDataWKTMapper GeometryDataWKTMapper = session.getMapper(GeometryDataWKTMapper.class);
            GeometryData one = GeometryDataWKTMapper.find(1L);
            System.out.println(one.getGeometry());
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    @Test
    public void testInsert() {
        try (SqlSession session = sqlSF.openSession()) {
            GeometryDataWKTMapper GeometryDataWKTMapper = session.getMapper(GeometryDataWKTMapper.class);
            GeometryData geometryData = new GeometryData();
            GeometryFactory geometryFactory = new GeometryFactory();
            Coordinate coordinate = new Coordinate(1, 1);
            Geometry geometry = geometryFactory.createPoint(coordinate);
            geometryData.setGeometry(geometry);
            long count = GeometryDataWKTMapper.insertOne(geometryData);
            System.out.println(count);
            session.commit();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            fail();
        }
    }

    @Test
    public void testUpdate() {
        try (SqlSession session = sqlSF.openSession()) {
            GeometryDataWKTMapper GeometryDataWKTMapper = session.getMapper(GeometryDataWKTMapper.class);
            GeometryData geometryData = new GeometryData();
            GeometryFactory geometryFactory = new GeometryFactory();
            Coordinate coordinate = new Coordinate(2, 2);
            Geometry geometry = geometryFactory.createPoint(coordinate);
            geometryData.setId(1L);
            geometryData.setGeometry(geometry);
            long count = GeometryDataWKTMapper.updateOne(geometryData);
            System.out.println(count);
            session.commit();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            fail();
        }
    }

    @Test
    public void testInsertList() {
        try (SqlSession session = sqlSF.openSession()) {
            GeometryDataWKTMapper GeometryDataWKTMapper = session.getMapper(GeometryDataWKTMapper.class);

            List<GeometryData> geometryDataList = new ArrayList<>();
            {
                GeometryData geometryData = new GeometryData();
                GeometryFactory geometryFactory = new GeometryFactory();
                Coordinate coordinate = new Coordinate(3, 3);
                Geometry geometry = geometryFactory.createPoint(coordinate);
                geometryData.setGeometry(geometry);
                geometryDataList.add(geometryData);
            }

            {
                GeometryData geometryData = new GeometryData();
                GeometryFactory geometryFactory = new GeometryFactory();
                LineString lineString = geometryFactory
                        .createLineString(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2) });
                geometryData.setGeometry(lineString);
                geometryDataList.add(geometryData);
            }

            {
                GeometryData geometryData = new GeometryData();
                GeometryFactory geometryFactory = new GeometryFactory();
                MultiLineString multiLineString = geometryFactory.createMultiLineString(new LineString[] {
                        geometryFactory
                                .createLineString(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2) }),
                        geometryFactory
                                .createLineString(new Coordinate[] { new Coordinate(3, 3), new Coordinate(4, 4) })
                });
                geometryData.setGeometry(multiLineString);
                geometryDataList.add(geometryData);
            }

            {
                GeometryData geometryData = new GeometryData();
                GeometryFactory geometryFactory = new GeometryFactory();
                MultiPolygon multiPolygon = geometryFactory.createMultiPolygon(new Polygon[] {
                        geometryFactory.createPolygon(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2),
                                new Coordinate(3, 3), new Coordinate(1, 1) }),
                        geometryFactory.createPolygon(new Coordinate[] { new Coordinate(4, 4), new Coordinate(5, 5),
                                new Coordinate(6, 6), new Coordinate(4, 4) })
                });
                geometryData.setGeometry(multiPolygon);
                geometryDataList.add(geometryData);
            }

            // {
            //     GeometryData geometryData = new GeometryData();
            //     GeometryFactory geometryFactory = new GeometryFactory();
            //     LinearRing linearRing = geometryFactory.createLinearRing(new Coordinate[] { new Coordinate(1, 1),
            //             new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(1, 1) });
            //     geometryData.setGeometry(linearRing);
            //     geometryDataList.add(geometryData);
            // }

            {
                GeometryData geometryData = new GeometryData();
                GeometryFactory geometryFactory = new GeometryFactory();
                MultiPoint multiPoint = geometryFactory.createMultiPointFromCoords(
                        new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2), new Coordinate(3, 3) });
                geometryData.setGeometry(multiPoint);
                geometryDataList.add(geometryData);
            }

            {
                GeometryData geometryData = new GeometryData();
                GeometryFactory geometryFactory = new GeometryFactory();
                Polygon polygon = geometryFactory.createPolygon(new Coordinate[] { new Coordinate(1, 1),
                        new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(1, 1) });
                geometryData.setGeometry(polygon);
                geometryDataList.add(geometryData);
            }

            // {
            //     GeometryData geometryData = new GeometryData();
            //     GeometryFactory geometryFactory = new GeometryFactory();
            //     GeometryCollection geometryCollection = geometryFactory.createGeometryCollection(new Geometry[] {
            //             geometryFactory.createPoint(new Coordinate(1, 1)),
            //             geometryFactory.createLineString(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2) }),
            //             geometryFactory.createPolygon(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2),
            //                     new Coordinate(3, 3), new Coordinate(1, 1) })
            //     });
            //     geometryData.setGeometry(geometryCollection);
            //     geometryDataList.add(geometryData);
            // }

            long count = GeometryDataWKTMapper.insertList(geometryDataList);
            System.out.println(count);
            session.commit();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            fail();
        }
    }

    @Test
    public void testInsertGeometryCollection() {
        try (SqlSession session = sqlSF.openSession()) {
            GeometryDataWKTMapper GeometryDataWKTMapper = session.getMapper(GeometryDataWKTMapper.class);
            GeometryData geometryData = new GeometryData();
            GeometryFactory geometryFactory = new GeometryFactory();
            GeometryCollection geometryCollection = geometryFactory.createGeometryCollection(new Geometry[] {
                    geometryFactory.createPoint(new Coordinate(1, 1)),
                    geometryFactory.createLineString(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2) }),
                    geometryFactory.createPolygon(new Coordinate[] { new Coordinate(1, 1), new Coordinate(2, 2),
                            new Coordinate(3, 3), new Coordinate(1, 1) })
            });
            geometryData.setGeometry(geometryCollection);
            Long index = GeometryDataWKTMapper.insertGeometryCollection(geometryData);
            System.out.println(index);
            session.commit();
        } catch(Exception e) {
            System.out.println(e.getMessage());
            fail();
        }
    }
}

在这里插入图片描述

建表SQL

CREATE TABLE `geometry_data` (
    `id` BIGINT(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `geometry` GEOMETRY NOT NULL COMMENT '几何信息',
    `create_time` timestamp  NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time` timestamp  NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
    `deleted` boolean DEFAULT false COMMENT '是否已被删除',
    PRIMARY KEY (`id`),
    SPATIAL INDEX `spatial_geometry` (`geometry`)
) COMMENT='几何数据表';

总结

很多数据库为了兼容Mysql,针对Geometry类型,在WKT模式下是兼容的。因为如何将WKT转换成自己数据库内部的结构,即对ST_GeomFromText等方法的实现是可以自己内部处理,让用户不会感知。这让WKT方案在跨数据库时有比较好的兼容性。
但是如果只是针对Mysql数据库,或者像OceanBase这类对Mysql底层也兼容很好的数据库,则可以考虑WKB方案。这块的内容我们会在《0基础学习Mybatis系列数据库操作框架——Mysql的Geometry数据处理之WKB方案》中介绍。

代码

https://github.com/f304646673/mybatis_demo

参考资料

  • https://dev.mysql.com/doc/refman/8.0/en/gis-data-formats.html#gis-wkb-format
  • https://dev.mysql.com/doc/refman/8.0/en/gis-wkt-functions.html#function_st-geomfromtext
  • https://www.keene.edu/campus/maps/tool/

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

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

相关文章

Spark项目实训(一)

目录 实验任务一&#xff1a;计算级数 idea步骤分步&#xff1a; 完整代码&#xff1a; linux步骤分布&#xff1a; 实验任务二&#xff1a;统计学生成绩 idea步骤分布&#xff1a; 完整代码&#xff1a; linux步骤分步&#xff1a; 实验任务一&#xff1a;计算级数 请…

如何在cPanel面板中开启盗链保护

本周有一个客户&#xff0c;购买Hostease的主机&#xff0c; 客户购买的是Linux虚拟主机&#xff0c;带cPanel面板的。询问我们的在线客服&#xff0c;如何可以防止他的网站上的图片不被盗用。cPanel的盗链保护功能可以帮助客户防止图片被盗链。 盗链&#xff08;Hotlinking&a…

代码随想录-算法训练营day46【动态规划08:单词拆分、多重背包!背包问题总结篇!】

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第九章 动态规划part08● 139.单词拆分 ● 关于多重背包&#xff0c;你该了解这些&#xff01; ● 背包问题总结篇&#xff01; 详细布置 关于 多重背包&#xff0c;力扣上没有相关的题目&#xff0c;所以今天大家的…

05.cv PIL torch

文章目录 opencvrectanglecircle保存图像 PILresize与Opencv的互操作 torchtensor的创建和定义Torch的自动梯度计算Torch的模块torch的训练流程 opencv plt.imshow 以RGB形式显示cv2.imread 读取的是BGR import cv2 image cv2.imread(image.png) #加载图像 print(image.shap…

Linux--软硬链接

目录 0.文件系统 1.软硬链接 1.1见一下软硬链接 1.2软硬链接的特征 1.3软硬链接是什么&#xff0c;有什么作用&#xff08;场景&#xff09; 0.文件系统 Linux--文件系统-CSDN博客 1.软硬链接 1.1见一下软硬链接 1.这是软链接 这个命令在Unix和Linux系统中用于创建一个符号…

什么是DNS缓存投毒攻击,有什么防护措施

随着企业组织数字化步伐的加快&#xff0c;域名系统&#xff08;DNS&#xff09;作为互联网基础设施的关键组成部分&#xff0c;其安全性愈发受到重视。然而&#xff0c;近年来频繁发生的针对DNS的攻击事件&#xff0c;已经成为企业组织数字化发展中的一个严重问题。而在目前各…

vue学习3:开发者调试工具的下载安装

极简插件官网_Chrome插件下载_Chrome浏览器应用商店 (zzzmh.cn) 测试运行程序 网页中右键检查

【Unity3D美术】URP渲染管线学习01

扫盲简介 URP渲染管线是Unity3d提供的一种视觉效果更好的渲染模式&#xff0c;类似的还有Built RP&#xff08;默认最普通的渲染模式&#xff09;\ HDRP(超高清&#xff0c;对设备要求高)&#xff0c;视觉效果好&#xff0c;而且占用资源少&#xff01;成为主流渲染管线模式&a…

十进制同步计数器

十进制同步计数器 使用最多的十进制计数器是按照 8421 BCD 码进行计数的电路 十进制同步加法计数器 【例1】设计一个十进制同步加法计数器&#xff0c;要求电路按 8421 BCD 码进行加法计数 Step1&#xff1a;建立原始状态转换图 Step2&#xff1a;选触发器&#xff0c;求方…

粉丝问,有没有UI的统计页面,安排!

移动应用的数据统计页面具有以下几个重要作用&#xff1a; 监控业务指标&#xff1a;数据统计页面可以帮助用户监控关键业务指标和数据&#xff0c;例如用户活跃度、销售额、转化率等。通过实时更新和可视化呈现数据&#xff0c;用户可以及时了解业务的整体状况和趋势。分析用…

LeetCode 128 最长连续序列(hot100) 解题思路分享

题干&#xff1a; 思路&#xff1a; 如果对时间复杂度没有要求的话&#xff0c;可以先排序&#xff0c;再一段一段地找&#xff0c;这样的好处是空间占用小。 如果希望On的话&#xff0c;那就采取设置一个Set的方法&#xff0c;这样空间复杂度是On&#xff0c;但是时间复杂度…

CPP Con 2020:Type Traits I

先谈谈Meta Programming 啥是元编程呢&#xff1f;很简单&#xff0c;就是那些将其他程序当作数据来进行处理和传递的编程&#xff08;私人感觉有点类似于函数式&#xff1f;&#xff09;这个其他程序可以是自己也可以是其他程序。元编程可以发生在编译时也可以发生在运行时。…

Python实现将LabelMe生成的JSON格式转换成YOLOv8支持的TXT格式

标注工具 LabelMe 生成的标注文件为JSON格式&#xff0c;而YOLOv8中支持的为TXT文件格式。以下Python代码实现3个功能&#xff1a; 1.将JSON格式转换成TXT格式&#xff1b; 2.将数据集进行随机拆分&#xff0c;生成YOLOv8支持的目录结构&#xff1b; 3.生成YOLOv8支持的YAML文件…

探索亚马逊云科技技术课程:大模型平台与提示工程的应用与优化

上方图片源自亚马逊云科技【生成式 AI 精英速成计划】技术开发技能课程 前言 学习了亚马逊云科技–技术开发技能课程 本课程分为三个部分&#xff0c;了解如何使用大模型平台、如何训练与部署大模型及生成式AI产品应用与开发&#xff0c;了解各类服务的优势、功能、典型使用案…

【QT八股文】系列之篇章2 | QT的信号与槽机制及通讯流程

【QT八股文】系列之篇章2 | QT的信号与槽机制及通讯流程 前言2. 信号与槽信号与槽机制介绍/本质/原理&#xff0c;什么是Qt信号与槽机制&#xff1f;如何在Qt中使用&#xff1f;信号与槽机制原理&#xff0c;解析流程Qt信号槽的调用流程信号与槽机制的优缺点信号与槽机制需要注…

【软考中级 软件设计师】数据结构

数据结构是计算机科学中一个基础且重要的概念&#xff0c;它研究数据的存储结构以及在此结构上执行的各种操作。在准备软考中级-软件设计师考试时&#xff0c;掌握好数据结构部分对于通过考试至关重要。下面是一些核心知识点概览&#xff1a; 基本概念&#xff1a; 数据结构定义…

在NVIDIA Jetson Nano上部署YOLOv5算法,并使用TensorRT和DeepStream进行加速

部署YOLOv5算法在NVIDIA Jetson Nano上并使用TensorRT和DeepStream进行加速涉及几个关键步骤。下面是一个详细的指南&#xff1a; 步骤 1: 准备YOLOv5模型 训练或下载预训练模型&#xff1a;首先&#xff0c;你需要有一个YOLOv5模型。你可以自己训练一个模型&#xff0c;或者…

响应式处理-一篇打尽

纯pc端响应式 pc端平常用到的响应式布局 大致就如下三种&#xff0c;当然也会有其他方法&#xff0c;欢迎评论区补充 将div height、width设置成100% flex布局 flex布局主要是将flex-wrap: wrap&#xff0c; 最后&#xff0c;你可以通过给子元素设置 flex 属性来控制它们的…

构建全面的无障碍学习环境:科技之光,照亮学习之旅

在信息与科技日益发展的当下&#xff0c;为所有人群提供一个包容和平等的学习环境显得尤为重要&#xff0c;特别是对于盲人朋友而言&#xff0c;无障碍学习环境的构建成为了一项亟待关注与深化的课题。一款名为“蝙蝠避障”的辅助软件&#xff0c;以其创新的设计理念与实用功能…

Excel 按顺序去重再编号

Excel的A有重复数据&#xff1a; A1Cow2Chicken3Horse4Butterfly5Cow 现在要去除重复&#xff0c;用自然数按顺序进行编号&#xff0c;结果写在相邻列&#xff1a; AB1Cow12Chicken23Horse34Butterfly45Cow1 使用 SPL XLL&#xff0c;输入公式并向下拖&#xff1a; spl(&q…