Linux framebuffer显示bmp图片

2023-11-17

  帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。

  framebuffer是LCD对应的一种HAL(硬件抽象层),提供抽象的,统一的接口操作,用户不必关心硬件层是怎么实施的。这些都是由Framebuffer设备驱动来完成的。

  帧缓冲设备对应的设备文件为/dev/fb*,如果系统有多个显示卡,Linux下还可支持多个帧缓冲设备,最多可达32个,分别为/dev/fb0到/dev/fb31,而/dev/fb则为当前缺省的帧缓冲设备,通常指向/dev/fb0,在嵌入式系统中支持一个显示设备就够了。帧缓冲设备为标准字符设备,主设备号为29,次设备号则从0到31,分别对应/dev/fb0-/dev/fb31。

  通过/dev/fb,应用程序的操作主要有这几种:

  • 读/写(read/write)/dev/fb:相当于读/写屏幕缓冲区。
  • 映射(map)操作:由于Linux工作在保护模式,每个应用程序都有自己的虚拟地址空间,在应用程序中是不能直接访问物理缓冲区地址的。而帧缓冲设备可以通过mmap()映射操作将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址上,然后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图了。
  • I/O控制:对于帧缓冲设备,对设备文件的ioctl操作可读取/设置显示设备及屏幕的参数,如分辨率,屏幕大小等相关参数。ioctl的操作是由底层的驱动程序来完成的。

  在应用程序中,操作/dev/fb的一般步骤如下:
1. 打开/dev/fb设备文件。
2. 用ioctl操作取得当前显示屏幕的参数,根据屏幕参数可计算屏幕缓冲区的大小。
3. 将屏幕缓冲区映射到用户空间。
4. 映射后即可直接读写屏幕缓冲区,进行绘图和图片显示。

  framebuffer相关数据结构介绍

  • fb_info结构体:帧缓冲设备中最重要的数据结构体,包括了帧缓冲设备属性和操作的完整性属性。定义显卡的当前状态;fb_info结构仅在内核中可见,在这个结构中有一个fb_ops指针。
  • fb_ops结构体:fb_info结构体的成员变量,fb_ops为指向底层操作的函数的指针。
  • fb_var_screen和fb_fix_screen结构体:fb_var_screen记录用户可以修改的显示控制器参数,之所以可以修改,是因为对同样的图形硬件,可以工作在不同的模式下。简单来讲,一个支持1024x768x24图形模式的硬件通常也能工作在800x600x16的图形模式下。可变的信息就是指Framebuffer的长度、宽度以及颜色深度等信息。
  • fb_fix_screen记录用户不能修改的显示控制器参数。比如图形硬件上实际的帧缓存空间的大小、能否硬件加速等信息。

  应用程序中通常要用到struct fb_var_screeninfo的下面这几个字段:
  xres、yres、bits_per_pixel,分别表示x轴的分辨率、y轴的分辨率以及每像素的颜色深度(颜色深度的单位为bit/pixel),其类型定义都是无符号32位整型数。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <errno.h>

//14byte文件头
typedef struct
{
    char    cfType[2];//文件类型,"BM"(0x4D42)
    int     cfSize;//文件大小(字节)
    int cfReserved;//保留,值为0
    int     cfoffBits;//数据区相对于文件头的偏移量(字节)
}__attribute__((packed)) BITMAPFILEHEADER;
//__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐

//40byte信息头
typedef struct
{
    char ciSize[4];//BITMAPFILEHEADER所占的字节数
    int  ciWidth;//宽度
    int  ciHeight;//高度
    char ciPlanes[2];//目标设备的位平面数,值为1
    int  ciBitCount;//每个像素的位数
    char ciCompress[4];//压缩说明
    char ciSizeImage[4];//用字节表示的图像大小,该数据必须是4的倍数
    char ciXPelsPerMeter[4];//目标设备的水平像素数/米
    char ciYPelsPerMeter[4];//目标设备的垂直像素数/米
    char ciClrUsed[4]; //位图使用调色板的颜色数
    char ciClrImportant[4]; //指定重要的颜色数,当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要
}__attribute__((packed)) BITMAPINFOHEADER;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    unsigned char reserved;
}__attribute__((packed)) PIXEL;//颜色模式RGB

BITMAPFILEHEADER FileHead;
BITMAPINFOHEADER InfoHead;

static char *fbp = 0;
static int xres = 0;
static int yres = 0;
static int bits_per_pixel = 0;
int width, height;

int show_bmp();
int fbfd = 0;

static void fb_update(struct fb_var_screeninfo *vi)   //将要渲染的图形缓冲区的内容绘制到设备显示屏来
{  
    vi->yoffset = 1;  
    ioctl(fbfd, FBIOPUT_VSCREENINFO, vi);  
    vi->yoffset = 0;  
    ioctl(fbfd, FBIOPUT_VSCREENINFO, vi);  
}  

static int cursor_bitmap_format_convert(char *dst,char *src)
{
    int i ,j ;
    char *psrc = src ;
    char *pdst = dst;
    char *p = psrc;

    /* 由于bmp存储是从后面往前面,所以需要倒序进行转换 */
    pdst += (width * height * 3);
    for(i=0;i<height;i++){
        p = psrc + (i+1) * width * 3;
        for(j=0;j<width;j++){
            pdst -= 3;
            p -= 3;
            pdst[0] = p[0];
            pdst[1] = p[1];
            pdst[2] = p[2];
        }
    }
    return 0;
}

int show_bmp(char *path)
{
    int i;
    FILE *fp;
    int rc;
    int line_x, line_y;
    long int location = 0, BytesPerLine = 0;
    char *bmp_buf = NULL;
    char *bmp_buf_dst = NULL;
    char * buf = NULL;
    int flen = 0;
    int ret = -1;
    int total_length = 0;

    printf("into show_bmp function\n");
    if(path == NULL)
    {
        printf("path Error,return\n");
        return -1;
    }
    printf("path = %s\n", path);
    fp = fopen( path, "rb" );
    if(fp == NULL){
        printf("load cursor file open failed\n");
        return -1;
    }

    /* 求解文件长度 */
    fseek(fp,0,SEEK_SET);
    fseek(fp,0,SEEK_END);

    flen = ftell(fp);
    printf("flen is %d\n",flen);

    bmp_buf = (char*)calloc(1,flen - 54);
    if(bmp_buf == NULL){
        printf("load > malloc bmp out of memory!\n");
        return -1;
    }

    /* 再移位到文件头部 */
    fseek(fp,0,SEEK_SET);

    rc = fread(&FileHead, sizeof(BITMAPFILEHEADER),1, fp);
    if ( rc != 1)
    {
        printf("read header error!\n");
        fclose( fp );
        return( -2 );
    }

    //检测是否是bmp图像
    if (memcmp(FileHead.cfType, "BM", 2) != 0)
    {
        printf("it's not a BMP file\n");
        fclose( fp );
        return( -3 );
    }
    rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
    if ( rc != 1)
    {
        printf("read infoheader error!\n");
        fclose( fp );
        return( -4 );
    }
    width = InfoHead.ciWidth;
    height = InfoHead.ciHeight;

    printf("FileHead.cfSize =%d byte\n",FileHead.cfSize);
    printf("flen = %d\n", flen);
    printf("width = %d, height = %d\n", width, height);

    total_length = width * height *3;

    printf("total_length = %d\n", total_length);

    //跳转的数据区
    fseek(fp, FileHead.cfoffBits, SEEK_SET);
    printf(" FileHead.cfoffBits = %d\n",  FileHead.cfoffBits);
    printf(" InfoHead.ciBitCount = %d\n",  InfoHead.ciBitCount);    

    //每行字节数
    buf = bmp_buf;
    while ((ret = fread(buf,1,total_length,fp)) >= 0) {
        if (ret == 0) {
            usleep(100);
            continue;
        }
        printf("ret = %d\n", ret);
        buf = ((char*) buf) + ret;
        total_length = total_length - ret;
        if(total_length == 0)
            break;
    }

    ///重新计算,很重要!!
    total_length = width * height *3;
    bmp_buf_dst = (char*)calloc(1,total_length );
    if(bmp_buf_dst == NULL){
        printf("load > malloc bmp out of memory!\n");
        return -1;
    }

    cursor_bitmap_format_convert(bmp_buf_dst, bmp_buf);
    memcpy(fbp,bmp_buf_dst,total_length);

    free(bmp_buf);
    free(bmp_buf_dst);

    fclose(fp);
    printf("show logo return 0\n");
    return 0;
}

int show_picture(int fd, char *path)
{
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int screensize = 0;
    struct fb_bitfield red;
    struct fb_bitfield green;
    struct fb_bitfield blue;

    //打开显示设备
    fbfd = fd;          //open("/dev/graphics/fb0", O_RDWR);
    printf("fbfd = %d\n", fbfd);
    if (fbfd == -1)
    {
        //printf("Error opening frame buffer errno=%d (%s)\n",errno, strerror(errno));
        return -1;
    }

    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
    {
        //printf("Error:reading fixed information.\n");
        return -1;
    }

    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
    {
        //printf("Error: reading variable information.\n");
        return -1;
    }

    //printf("R:%x ;G:%d ;B:%d \n", (int)vinfo.red, vinfo.green, vinfo.blue );
    //printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );

    xres = vinfo.xres;
    yres = vinfo.yres;
    bits_per_pixel = vinfo.bits_per_pixel;

    //计算屏幕的总大小(字节)
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    printf("screensize=%ld byte\n",screensize);

    //对象映射
    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if (fbp == (char *)-1)
    {
        printf("Error: failed to map framebuffer device to memory.\n");
        return -1;
    }

    printf("sizeof file header=%ld\n", sizeof(BITMAPFILEHEADER));

    //显示图像
    show_bmp(path);

    ///在屏幕上显示多久
    sleep(100);

    fb_update(&vinfo);

    //删除对象映射
    munmap(fbp, screensize);

    return 0;
}

int main()
{
    int fbfd = 0;

    fbfd = open("/dev/fb0", O_RDWR);  
    if (!fbfd)  
    {  
        printf("Error: cannot open framebuffer device.\n");  
        exit(1);  
    } 
    show_picture(fbfd, "./girl.bmp");

    close(fbfd);
}

  这里我们是使用qemu模拟的,否则用主机会打乱工作环境! 首先按照我以前博文:
linux内核调试环境搭建搭建起来一个最小linux环境。

  注意到在编译内核的时候要加入一个内核配置选项,不然内核不支持 qemu 显卡设备,也就无法创建/dev/fb0 设备文件。

CONFIG_DRM_CIRRUS_QEMU=y
config DRM_CIRRUS_QEMU
    tristate "Cirrus driver for QEMU emulated device"
    depends on DRM && PCI
    select FB_SYS_FILLRECT
    select FB_SYS_COPYAREA
    select FB_SYS_IMAGEBLIT
    select DRM_KMS_HELPER
    select DRM_KMS_FB_HELPER
    select DRM_TTM
    help
     This is a KMS driver for emulated cirrus device in qemu.
     It is *NOT* intended for real cirrus devices. This requires
     the modesetting userspace X.org driver.

配置位置:

    Device Drivers  --->
        Graphics support  --->
            Direct Rendering Manager  --->
                Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)  --->
                <*> Cirrus driver for QEMU emulated device

qemu启动命令行参数如下:

qemu -m 512 -kernel bzImage -append "root=/dev/sda rw" -boot c -hda busybox.img -k en-us -vga cirrus -net nic -net tap,ifname=tap0,script=no

  启动qemu之后,打开上面代码编译的应用程序可见bmp文件被完整的显示出来:
这里写图片描述

  上面代码中调用函数 cursor_bitmap_format_convert 是由于bmp图象是从下至上存储的,所以我们不能进行直接顺序读取。详细的说,bmp图象存储区数据是从1078偏移字节开始。文件内第一个图象点实际上是对应图象(320*200)第200行的最左边的第一个点,而从1078开始的320个点则是图象最下面一行对应的点,之后的321个点是图象倒数第二行最左边的第一个点。这样,bmp文件最后一个字节对应的点是第一行最后边的点了。

关于bmp文件格式这里就不分析了,相对于jpeg等压缩格式,这个格式十分简单网上很多资料

注意:上面的程序只在framebuffer上显示图片,却没有删除刷新屏幕,可以使用下面的命令恢复屏幕

保存屏幕信息:dd if=/dev/fb0 of=fbfile 或: cp /dev/fb0 fbfile
恢复屏幕信息:dd if=fbfile of=/dev/fb0 或: cat fbfile > /dev/fb0

bmp 位图文件:

drop上的文件,似乎这几天ss很难用,过几天再放上原图
就是一个PC bitmap, Windows 3.x format, 1024 x 768 x 24 位图文件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux framebuffer显示bmp图片 的相关文章

  • 使用 grep 查找包含所有搜索字符串的行

    我有一个文件 其中包含很多与此类似的行 id 2796 some model Profile message type MODEL SAVE fields account 14 address null modification times
  • 如何使用 bash 锁定文件

    我有一个任务从远程服务器同步目录 rsync av email protected cdn cgi l email protection srv data srv data 为了使其定期运行并避免脚本 reEnter 问题 我使用 rsyn
  • 如何禁用 GNOME 桌面屏幕锁定? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何阻止 GNOME 桌面在几分钟空闲时间后锁定屏幕 我已经尝试过官方手册了在红帽 https access redhat com doc
  • Jenkins中找不到环境变量

    我想在詹金斯中设置很多变量 我试过把它们放进去 bashrc bash profile and profile of the jenkins用户 但 Jenkins 在构建发生时找不到它们 唯一有效的方法是将所有环境变量放入Jenkinsf
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 大多数 Linux 系统头文件与 C++ 兼容吗?

    大多数 Linux 系统头文件 API C 兼容吗 今天我试图做这样的事情 include
  • 无法从 jenkins 作为后台进程运行 nohup 命令

    更新 根据下面的讨论 我编辑了我的答案以获得更准确的描述 我正在尝试从詹金斯运行 nohup 命令 完整的命令是 nohup java jar home jar server process 0 35 jar prod gt gt var
  • fopen 不返回

    我在 C 程序中使用 fopen 以只读模式 r 打开文件 但就我而言 我观察到 fopen 调用没有返回 它不返回 NULL 或有效指针 执行在 fopen 调用时被阻止 文件补丁绝对正确 我已经验证过 并且不存在与权限相关的问题 任何人
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 无法使用 wget 在 CentOS 机器上安装 oracle jdk

    我想在CentOS上安装oracle java jdk 8 我无法安装 java jdk 因为当我尝试使用命令安装 java jdk 时 root ADARSH PROD1 wget no cookies no check certific
  • Pyaudio 安装错误 - “命令‘gcc’失败,退出状态 1”

    我正在运行 Ubuntu 11 04 Python 2 7 1 并想安装 Pyaudio 于是我跑了 sudo easy install pyaudio 在终端中 进程退出并显示以下错误消息 Searching for pyaudio Re
  • 如何在Linux内核源代码中打印IP地址或MAC地址

    我必须通过修改 Linux 内核源代码来稍微改变 TCP 拥塞控制算法 但为了检查结果是否正确 我需要记录 MAC 或 IP 地址信息 我使用 PRINTK 函数来打印内核消息 但我感觉很难打印出主机的MAC IP地址 printk pM
  • Linux 可执行文件与 OS X“兼容”吗?

    如果您在基于 Linux 的平台上用 C 语言编译一个程序 然后将其移植以使用 MacOS 库 它会工作吗 来自编译器的核心机器代码在 Mac 和 Linux 上兼容吗 我问这个问题的原因是因为两者都是 基于 UNIX 的 所以我认为这是真
  • -[EAGLContext renderbufferStorage:fromDrawable:] 第二次失败?

    我正在开发一个 iOS openGL ES 应用程序 我正在做通常的 EAGLView ES2Render 的事情 启动时 使用以下代码成功创建 frambuffer BOOL createFramebuffers EAGLContext
  • 在 Linux 上使用多处理时,TKinter 窗口不会出现

    我想生成另一个进程来异步显示错误消息 同时应用程序的其余部分继续 我正在使用multiprocessingPython 2 6 中的模块来创建进程 我试图用以下命令显示窗口TKinter 这段代码在Windows上运行良好 但在Linux上
  • 使用 sh 运行 bash 脚本

    我有 bash 脚本 它需要 bash 另一个人尝试运行它 sh script name sh 它失败了 因为 sh 是他的发行版中 dash 的符号链接 ls la bin sh lrwxrwxrwx 1 root root 4 Aug
  • ubuntu:升级软件(cmake)-版本消歧(本地编译)[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我的机器上安装了 cmake 2 8 0 来自 ubuntu 软件包 二进制文件放置在 usr bin cmake 中 我需要将 cmake 版本至少
  • 多处理:仅使用物理核心?

    我有一个函数foo它消耗大量内存 我想并行运行多个实例 假设我有一个有 4 个物理核心的 CPU 每个核心有两个逻辑核心 我的系统有足够的内存来容纳 4 个实例foo并行但不是 8 个 此外 由于这 8 个核心中的 4 个是逻辑核心 我也不
  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • 如何确保应用程序在 Linux 上持续运行

    我试图确保脚本在开发服务器上保持运行 它会整理统计数据并提供网络服务 因此它应该会持续存在 但一天中有几次 它会因未知原因而消失 当我们注意到时 我们只需再次启动它 但这很麻烦 并且某些用户没有权限 或专有技术 来启动它 作为一名程序员 我

随机推荐

  • 图形学相关期刊和会议的基本信息

    目录 期刊 A类 ACM TOG A类 IEEE TIP A类 IEEE TVCG B类 TOMCCAP B类 CAGD B类 CGF B类 CAD B类 GM B类 TCSVT B类 TMM B类 SIIMS C类 CGTA C类 CAV
  • Webshell工具的流量特征分析(菜刀,蚁剑,冰蝎,哥斯拉)

    0x00 前言 使用各种的shell工具获取到目标权限 即可进行数据操作 今天来简要分析一下目前常使用的各类shell管理工具的流量特诊 帮助蓝队同学在风险识别上快速初值 0x01 中国菜刀流量分析 payload特征 PHP ASP AS
  • ElasticSearch系列-索引原理与数据读写流程详解

    索引原理 倒排索引 倒排索引 Inverted Index 也叫反向索引 有反向索引必有正向索引 通俗地来讲 正向索引是通过key找value 反向索引则是通过value找key ES底层在检索时底层使用的就是倒排索引 索引模型 现有索引和
  • JAVA(Object和String)一 Object类和String字符串的理解和使用

    JAVA Object和String 一 Object类和String字符串的理解和使用 Object类 String类 Object类 理解 在JAVA中有一个非常特殊的类叫做Object类 JAVA里面所有的类都继承自Object类 我
  • Git下载/查看/切换/新建分支

    1 git下载指定分支代码 git clone b branchname https github com xxx xxx git 2 看分支 git branch 列出本地已经存在的分支 并且当前分支会用 标记 git branch r
  • Element ui Dialog弹出框宽度固定不变

    一般我们引用Dialog弹出框时 弹出框的大小都是用width 30 这样来设置 这样的话我们在缩小屏幕的时候弹出框就会根据你缩小屏幕的宽度的百分比来设置 这样你弹出框里面的东西就会溢出 如果你不想溢出就把宽度写成width 500px 这
  • 文件上传服务器例子,服务器端的程序优化

    package cn dali4 code04ex 此程序优化了文件名 这样可以随机生成文件名 给服务器写了循环 可以一直监听 开启了多线程 优化了执行的效率 import java io import java net ServerSoc
  • C++代码注释详解

    常用注释语法 注释写在对应的函数或变量前面 JavaDoc类型的多行注释风格如下 这里为注释 一般注释中有简要注释和详细注释 简要注释有多种标识方式 这里推荐使用 brief命令强制说明 例如 brief 这里为简要注释 这里为详细注释 b
  • 正确使用g2o各类线性方程求解器

    g2o LinearSolverEigen g2o LinearSolverDense g2o LinearSolverCSparse g2o LinearSolverCholmod是常用的线性方程求解器 一套可运行程序 包括不同梯度下降优
  • Python中的异常处理raise介绍

    文章目录 0 介绍 1 raise 介绍 案例 2 raise 不需要参数 案例 3 raise 单独一个 raise 正常程序使用无参的 raise 4 其它案例 4 1 案例1 4 2 案例2 5 处理流程 总结 0 介绍 问题1 是否
  • eslint 搭配 vscode 的简单使用

    前言 刚开始时 由于嫌麻烦 并没有安装eslint 最近在新的项目上使用了eslint再配合vscode的插件 真是爽的不要太爽 因此打算写一篇简单的食用说明来记录食用过程 前期准备 没啥好准备的 作为开发肯定是具备yarn和node的 编
  • WINDOWS键盘钩子

    最近有个需求做的时候碰到需要捕获某个程序的特定按键并且在该程序处于焦点并且按下特定键 如F1 时让主板的蜂鸣器响一声以提示 由于该程序没有源码 因此只能通过编写服务挂全局钩子来对该程序的键盘消息进行捕获 大致的代码结构是使用VC现编写了一个
  • Linux Debian上快速安装Docker并运行

    要在Debian上安装Docker 可以按照以下步骤进行 更新系统软件包 在终端中执行以下命令 更新系统软件包 sudo apt get update 安装依赖包 在终端中执行以下命令 安装Docker需要的依赖包 sudo apt get
  • Echarts折线图x轴刻度距离

    在 ECharts 折线图中 x 轴刻度的距离是根据数据的数量和实际绘图区域的宽度来确定的 ECharts 会根据数据的数量自动计算出 x 轴上每个刻度之间的距离 以适应绘图区域的宽度 如果希望手动设置 x 轴刻度的距离 可以使用以下两种方
  • 解决PowerDesigner里允许字段重名约束的设置问题

    让tomcat支持中文路径名 将conf server xml中的
  • mfc入门基础(六)创建模态对话框与非模态对话框

    参考博客 VS2010 MFC编程入门之十一 对话框 模态对话框及其弹出过程 软件开发 鸡啄米 一 创建模态对话框 1 接着上节中的test02的例子来讲 找到test02 cpp文件 找到函数InitInstance 然后 因为上节我们实
  • setuptools清华源_setuptools与pip的依赖关系解决方案之间的差异

    我最近开始用SetupTools打包我的第一个项目 并且大部分都取得了成功 setuptools与pip的依赖关系解决方案之间的差异 不幸的是 我遇到了一个令人困惑的情况 我的项目依赖于PyPI上没有的单个文件模块 我已经能够使用depen
  • RandLA-Net结果可视化(将结果保存到本地再通过cloudcompare可视化)

    RandLA Net结果可视化 将结果保存到本地再通过cloudcompare可视化 问题 RandLA Net官网提供代码的可视化部分是通过open3d的方式呈现的 但如果使用远端服务器去跑 可能就无法实现可视化 或者当我们的需要可视化的
  • 卷积神经网络及其在图像处理中的应用

    一 前言 卷积神经网络 Constitutional Neural Networks CNN 是在多层神经网络的基础上发展起来的针对图像分类和识别而特别设计的一种深度学习方法 先回顾一下多层神经网络 多层神经网络包括一个输入层和一个输出层
  • Linux framebuffer显示bmp图片

    帧缓冲 framebuffer 是Linux为显示设备提供的一个接口 把显存抽象后的一种设备 他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作 framebuffer是LCD对应的一种HAL 硬件抽象层 提供抽象的 统一的接口操作