Android Bitmap图像处理(1)- 图片压缩

2023-10-31

一直以来Bitmap都是开发中很棘手的问题,这个问题就是传说中的OOM(java.lang.OutofMemoryError - 内存溢出),那么Bitmap为何如此丧失,令无数Android开发者所懊恼?

一、Bitmap引发OOM的原因

  1. 由于每个机型在编译ROM时都设置了一个应用堆内存VM值上限dalvik.vm.heapgrowthlimit,用来限定每个应用可用的最大内存,超出这个最大值将会报OOM。这个阀值,一般根据手机屏幕dpi大小递增,dpi越小的手机,每个应用可用最大内存就越低。例如我的Z3c,xhdpi的VM阀值是192M,但是到了nexus s hdpi上只有可怜的48M。这样,当一个activity中加载多张大图后,就很容易OOM了。有关应用内存阀值的参考可以看这里3.7节:
    http://static.googleusercontent.com/media/source.android.com/en//compatibility/android-cdd.pdf

  2. 图片分辨率越高,消耗的内存越高,当加载高分辨率图片的时候,将会非常占用内存,一旦处理不当就会OOM。例如,一张500W像素的照片的分辨率是:2592x1936。如果Bitmap使用 ARGB_8888 32位来平铺显示的话,占用的内存是2592x1936x4个字节,占用将近19M内存,my god,加载不到10张这种高质量照片,应用将直接挂掉,报OOM

  3. 在使用ListView, GridView等这些大量加载view的组件时,如果没有合理的处理缓存,大量加载Bitmap的时候,也将容易引发OOM

二、介绍Bitmap

工欲善其事必先利其器,想要高效加载Bitmap,了解Bitmap是必不可少的。Bitmap有几个重要的成员变量和方法,下面开始介绍:

2.1 Bitmap.Config

一张图片Bitmap所占用的内存 = 图片长度 x 图片宽度 x 一个像素点占用的字节数
而Bitmap.Config,正是指定单位像素占用的字节数的重要参数。

其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。

  • ALPHA_8
    表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
  • ARGB_4444
    表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
  • ARGB_8888
    表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
  • RGB_565
    表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节

Bitmap.Config主要作用是:以何种方式像素存储。不同的配置将会影响图像的画质(色彩深度),位数越高画质越高,显然在这里ARGB_8888是最占内存的。当然,画质越高也就越占内存了。

Tips:由于ARGB_4444的画质惨不忍睹,一般假如对图片没有透明度要求的话,可以改成RGB_565,相比ARGB_8888将节省一半的内存开销。

2.1.1 配置不同Bitmap.Config在相同分辨率下的占用内存情况

一张图片Bitmap所占用的内存 = 图片长度 x 图片宽度 x 一个像素点占用的字节数

Bitmap.Config 分辨率100x100的图片占用内存的大小
ALPHA_8 100x100x1 = 10000 byte ~= 9.77 KB
ARGB_4444 100x100x2 = 20000 byte ~= 19.53 kb
ARGB_8888 100x100x4 = 40000 byte ~= 39.06 KB
RGB_565 100x100x2 = 20000 byte ~= 19.53 KB
2.2 Bitmap.CompressFormat

从字面上理解,它的含义是:Bitmap压缩格式

public enum CompressFormat {
    JPEG    (0),
    PNG     (1),
    WEBP    (2);

    CompressFormat(int nativeInt) {
        this.nativeInt = nativeInt;
    }
    final int nativeInt;
}

嗯,其实这个参数很简单,就是指定Bitmap是以JPEG、PNG还是WEBP格式来压缩

2.3 Bitmap.compress()方法

重磅方法来了,通过这个方法,可以实现图片的压缩。使用该方法需要传三个参数进去:CompressFormat、int类型的quality、OutputStream

  • CompressFormat
    指定Bitmap的压缩格式,可选择JPEG、PNG、WEBP
  • int类型的quality
    指定Bitmap的压缩品质,范围是0 ~ 100;该值越高,画质越高。0表示画质最差,100画质最高。

  • OutputStream
    指定Bitmap的字节输出流。一般使用:

    ByteArrayOutputStream stream = new ByteArrayOutputStream();

    // Bitmap.compress()方法
    public boolean compress(CompressFormat format, 
    int quality, OutputStream stream) {
    
        if (stream == null) {
            throw new NullPointerException();
        }
        if (quality < 0 || quality > 100) {
            throw new IllegalArgumentException("quality must be 0..100");
        }
        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
        boolean result = nativeCompress(mFinalizer.mNativeBitmap, format.nativeInt,
                quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
        return result;
    }
    
2.3.1 案例:将一个Bitmap压缩成jpeg, quality为10,代码如下:
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_test3);

    ImageView iv_1 = (ImageView) findViewById(R.id.iv_1);
    ImageView iv_2 = (ImageView) findViewById(R.id.iv_2);

    Bitmap bmp = BitmapFactory.
    decodeResource(this.getResources(), R.mipmap.test_pic);

    iv_1.setImageBitmap(bmp);

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.JPEG, 10, bos);

    byte[] bytes = bos.toByteArray();
    bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

    iv_2.setImageBitmap(bmp);
}

运行效果图:【下面那张图明显要比上一张画质差了很多】

三、介绍BitmapFactory

从上面那个案例的代码可以发现,获取Bitmap不是通过构造new出来的,而是通过BitmapFactory”制造”出来的。BitmapFactory是获取Bitmap和压缩Bitmap的重要类,下面开始介绍BitmapFactory几个重要的成员变量和方法:

3.1 通过BitmapFactory解码(获取)Bitmap的几种方式
  • decodeFile()   //从SD卡文件读取

    Bitmap bm = BitmapFactory.decodeFile(Environment.
    getExternalStorageDirectory().getAbsolutePath()+"/photo.jpg");
    
  • decodeResource()   //从资源文件res读取

    Bitmap bm = BitmapFactory.
    decodeResource(this.getResources(), R.mipmap.test_pic);
    
  • decodeStream()   //从输入流读取

    Bitmap bm = BitmapFactory.decodeStream(inputStream);
    
  • decodeByteArray()   //从字节数组读取

    Bitmap bm = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    
3.2 BitmapFactory.Options

BitmapFactory在使用方法decodeFile()、decodeResource()解码图片时,可以指定它的BitmapFactory.Options。这个参数作用非常大,它可以设置Bitmap的采样率,通过改变图片的宽度、高度、缩放比例等,以达到降低图片的像素的目的,这样可以做到图片压缩,减少Bitmap的内存

下面列出BitmapFactory.Options的部分成员变量:

public Bitmap inBitmap;

public boolean inJustDecodeBounds;

public int inSampleSize;

public int inDensity;

public int inTargetDensity;

public int inScreenDensity;

public boolean inScaled;

public int outWidth;

public int outHeight;

public String outMimeType;

看到这么多成员变量是不是傻了?no,no,no,其实很简单。一句话总结:in开头的代表的就是设置某某参数;out开头的代表的就是获取某某参数。比如,inSampleSize就是设置Bitmap的缩放比例、outWidth就是获取Bitmap的高度。

3.2.1 inJustDecodeBounds 设置只去读图片的附加信息(宽高),不去解析真实的Bitmap

从字面上理解,它的含义是:”设置仅解码Bitmap的边界”。那它真正的作用是啥呢?

当inJustDecodeBounds设置为true的时候,BitmapFactory通过decodeResource或者decodeFile解码图片时,将会返回空(null)的Bitmap对象,这样可以避免Bitmap的内存分配,但是它可以返回Bitmap的宽度、高度以及MimeType。

// 当inJustDecodeBounds设置为true时,获取Bitmap的宽度、高度以及MimeType
BitmapFactory.Options options =  new BitmapFactory.Options(); 
options.inJustDecodeBounds =  true ; 
BitmapFactory.decodeResource (getResources(), R.id.myimage, options); 
int imageHeight = options.outHeight ; 
int imageWidth = options.outWidth ; 
String imageType = options.outMimeType ;

那么这样做有何意义呢?看完下面这段代码,你就知道这样做有啥意义了。意义就在于,可以先不用产生Bitmap内存,从而获得图片的宽高信息,尽可能的做到节约内存。

3.2.1.1 通过BitmapFactory.Options根据手机屏幕尺寸设置图片的缩放比例
// 根据手机屏幕尺寸设置图片的缩放比例【将大图缩放】
public class TestThreadActivity3 extends Activity {

@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_test3);

    ImageView iv_1 = (ImageView) findViewById(R.id.iv_1);
    ImageView iv_2 = (ImageView) findViewById(R.id.iv_2);

    BitmapFactory.Options opts = new BitmapFactory.Options();

    opts.inJustDecodeBounds = true;  //只去读图片的头信息,不去解析真实的位图      
    Bitmap bmp = BitmapFactory.decodeResource(this.getResources(),
     R.mipmap.test_pic2,opts);

    WindowManager wm  = getWindowManager();

    int screenWidth = wm.getDefaultDisplay().getWidth();//得到屏幕的宽度
    int screenheight = wm.getDefaultDisplay().getHeight();//得到屏幕的高度

    Log.e("屏幕宽度:",screenWidth+"");
    Log.e("屏幕高度:", screenheight + "");

    int picWidth = opts.outWidth;// 得到图片宽度
    int picHeight = opts.outHeight;// 得到图片高度
    Log.e("原图片高度:",picHeight+"");
    Log.e("原图片宽度:", picWidth + "");

    //计算图片缩放比例
    int dx = picWidth/screenWidth;
    int dy = picHeight/screenheight;
    Log.e("dx,dy",dx+","+dy+"");
    int scale = 1;
    if(dx>=dy&&dy>=1){
        Log.e("按照水平方向缩放:" ,dx+"");
        scale = dx;
    }
    if(dy>dx&&dx>=1){
        Log.e("按照竖直方向缩放:", dy + "");
        scale = dy;
    }

    opts.inSampleSize = scale;//设置缩放比例
    opts.inJustDecodeBounds = false;//真正的去解析位图
    bmp = BitmapFactory.decodeResource(this.getResources(), R.mipmap.test_pic2,opts);
    int picWidth2 = opts.outWidth;// 得到图片宽度
    int picHeight2 = opts.outHeight;// 得到图片高度
    Log.e("压缩后的图片宽度:",picWidth2+"");
    Log.e("压缩后的图片高度:", picHeight2 + "");
    Log.e("压缩后的图占用内存:",bmp.getByteCount()+"");
    iv_2.setImageBitmap(bmp);
}

}

我们读取一张3840x2400的图片运行结果:
原图直接占用36M内存,如果直接设置的话将瞬间爆炸报OOM。所以我们这里先不加载Bitmap,而是只获取宽和高,待缩放后,再进行真实的加载Bitmap。

3.2.2 inSampleSize 设置图片的缩放比例(宽和高)

在这里着重讲一下这个inSampleSize。从字面上理解,它的含义是:”设置取样大小“。它的作用是:设置inSampleSize的值(int类型)后,假如设为4,则宽和高都为原来的1/4,宽高都减少了,自然内存也降低了。

在这里参考Google官方文档来解释:
http://developer.android.com/intl/zh-cn/training/displaying-bitmaps/load-bitmap.html#load-bitmap

如何理解”设置取样大小“呢?如果你认真看了上面的内容话,聪明的你一定知道,肯定需要配合inJustDecodeBounds,先获取图片的宽、高【这个过程就是取样】,然后通过获取的宽高,动态的设置inSampleSize的值。

【当然,你也可以不动态,可以写死inSampleSize的值。比如设置inSampleSize = 4的话,一张分辨率为2048x1536px的图像将使用inSampleSize值为4的设置来解码,产生的Bitmap大小约为512*384px。相较于完整图片占用12M的内存,这种方式只需0.75M内存(假设Bitmap配置为ARGB_8888)。】

这里再举例演示一个动态设置inSampleSize的案例代码,可以通过设置图片宽高来缩放图片尺寸:

public class TestThreadActivity3 extends Activity {

@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_test3);

    ImageView iv_1 = (ImageView) findViewById(R.id.iv_1);
    ImageView iv_2 = (ImageView) findViewById(R.id.iv_2);

    BitmapFactory.Options opts = new BitmapFactory.Options();

    opts.inJustDecodeBounds = true;   //只去读图片的附加信息,不去解析真实的位图

    Bitmap bmp = BitmapFactory.
    decodeResource(this.getResources(), R.mipmap.test_pic,opts);


    Log.e("原图占用内存:", bmp.getByteCount() + "");
    iv_1.setImageBitmap(bmp);

    int picWidth = opts.outWidth;// 得到图片宽度
    int picHeight = opts.outHeight;// 得到图片高度

    Log.e("原图片高度:",picHeight+"");
    Log.e("原图片宽度:",picWidth+"");

      //根据100*100的宽高,设置缩放比例
    opts.inSampleSize = calculateInSampleSize(opts,100,100);
    opts.inJustDecodeBounds = false;//真正的去解析位图

    bmp = BitmapFactory.decodeResource(this.getResources(), R.mipmap.test_pic, opts);
    Log.e("压缩后的图占用内存:",bmp.getByteCount()+"");
    iv_2.setImageBitmap(bmp);
}

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {

    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }
    Log.e("inSampleSize:",inSampleSize+"");
    return inSampleSize;
}

}

将图片压缩成100x100px分辨率的运行结果:

四、总结(Bitmap压缩的几种方法)

1、Bitmap压缩的两种常用方法

  • 质量压缩法 Bitmap.compress()
    参考2.3.1节的代码
  • 取样压缩法 设置inSampleSize的值
    参考3.2.1.1 和 3.2.2的代码

2、在实际使用中可以结合质量压缩法和取样压缩法一起用,以达到最佳压缩效果。

3、看完了这篇内容,其实说白了,Bitmap压缩都是围绕这个来做文章:Bitmap所占用的内存 = 图片长度 x 图片宽度 x 一个像素点占用的字节数。3个参数,任意减少一个的值,就达到了压缩的效果。

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

Android Bitmap图像处理(1)- 图片压缩 的相关文章

  • 设置 CollapsingToolbarLayout 的起始高度

    我希望能够在 CollapsingToolbarLayout 内的 ImageView 上滚动 那么这怎么可能 以及如何设置该图像视图的起始高度 我的 ImageView 高度是 280p 在活动开始时我想显示 200p 然后我可以向下滚动
  • 有没有办法有一个屏蔽数字输入字段?

    我正在 Android 上创建一个 HTML5 应用程序 对于这个特定场景 我们有一个用于信用卡安全代码的输入字段 我们希望强制输入字段仅包含数字并被屏蔽 我没有运气搜索这个特定的案例 从我自己研究 尝试中可以看出 这不能纯粹通过 HTML
  • OneSignal 推送通知 单击以打开活动

    我集成了一个用于推送通知的信号库 我想在应用程序未运行时通过单击推送通知来打开特定活动 我收到推送通知 但当我单击通知时 应用程序崩溃了 这是我的通知接收器代码 public class ExampleNotificationOpenedH
  • Android - 如何获取文本视图中字符的坐标

    是否可以从 Android 中的 TextView 中的字符获取 x 坐标 我不是在寻找 TextView 本身的坐标 我需要 TextView 中最后一个字符的坐标 多行 提前致谢 Java解决方案 以下是如何获得x and y特定字符的
  • Android:对于具有 LinearLayout 定义的成员的 ListView,上下文菜单不显示?

    我有一个 ListActivity 和 ListView 并且我已将一些数据绑定到它 数据显示得很好 而且我还为视图注册了一个上下文菜单 当我将列表项显示为简单的 TextView 时 它工作正常
  • 检查从 arrayadapter 获取的复选框

    我有标题清单 CheckBox 我想控制默认检查哪一个 所以我试图获得正确的视图并检查它 但由于某种原因它不起作用 知道为什么吗 form checkbox item xml
  • Android - 如何在 ListView 的背景上显示垂直线(并根据行高)?

    如何在背景上显示一条垂直线 如下图蓝色突出显示的那条 在此示例中 我有一个带有 ImageView 元素的 ListView 和 TextView 但它与线条无关 并且我希望这些项目的背景上有一条垂直线 让人感觉它们与每个项目 连接 另请注
  • __stack_chk_fail_local 和 -fno-stack-protector - 如何让它工作?

    Update 我刚刚发现问题出在我的项目 libxml2 中包含的预构建库上 它是在启用堆栈保护的情况下构建的 因此依赖于 stack chk fail local方法 我现在已经重建了该库 fno stack protector也是 一切
  • 如何在 Android 应用程序中使用 xmlserializer 创建 xml

    您好 我正在制作一个预订应用程序 我需要在创建 xml 后将 xml 发送到服务器 如何使用创建 xmlxmlserializer创建后将其发送到服务器 http api ean com ean services rs hotel v3 l
  • Firebase 云消息传递 - 目标到 Firebase 控制台中不可见的单个设备

    我正在尝试向 android 中的单个设备发送通知 但是当我从 Firebase 控制台执行此操作时 它在 Firebase 新视图中不可见 谁能帮助我从哪里向单个设备发送通知 仔细尝试以下步骤 Tap 新通知 Fill up 通知标题 可
  • 如何计算android中位图擦除区域的百分比?

    我是安卓新手 我正在制作一个可以使用手指擦除画布上的位图的应用程序 像手指画橡皮擦之类的东西 我想计算擦除区域的百分比 例如 60 已从完整图像中擦除 请帮助我做到这一点 提前致谢 我尝试了一些方法 它总是给我 0 它不起作用 请参阅该方法
  • 像 Google Play 商店一样在垂直 RecyclerView 中动态不同图像水平 RecyclerView

    我一直在关注这个教程 http android pratap blogspot co za 2015 12 horizo ntal recyclerview in vertical html http android pratap blog
  • Android:TelephonyManager 类

    我不明白为什么 API 文档中这么写TelephonyManager类是public 但是当我尝试创建一个实例时 它说它不是公共类 并且无法从包中访问 我看到它也说使用Context getSystemService Context TEL
  • 如何使用Multipart将图像上传到php服务器

    我一直很头疼 如何将图像上传到服务器 这对我来说是新任务 但对我来说很困惑 我在 stackoverflow 上搜索并用谷歌搜索 但我遇到了问题 我的意图是从 SD 卡上传照片并从相机拍照并上传到服务器 在ios中 这个任务已经完成 在io
  • 在 Android 模拟器中获取互联网连接

    我有一台带有wifi连接的台式电脑 我的IP地址是192 168 12 95 网关是192 168 10 10 但是我在android模拟器中没有获得互联网连接 也就是说我无法访问internate 我也尝试过 emulator avd w
  • 如何在java中从包含.0的浮点数中删除小数部分

    我只想删除包含的浮点数的小数部分 0 所有其他数字都是可以接受的 例如 I P 1 0 2 2 88 0 3 56666 4 1 45 00 99 560 O P 1 2 2 88 3 567 4 1 45 99 560 有什么方法可以做到
  • SQlite 获取最近的位置(带有纬度和经度)

    我的 SQLite 数据库中存储有纬度和经度的数据 我想获取距我输入的参数最近的位置 例如我当前的位置 纬度 经度等 我知道这在 MySQL 中是可能的 并且我已经做了相当多的研究 SQLite 需要一个自定义外部函数来实现半正弦公式 计算
  • 找不到R类

    当我打开 Eclipse 时 R class在我的项目中消失了 为什么 我有 eclipse juno 和最新版本的 android SDK The R class不会重新生成 因为代码中有错误 我怎么解决这个问题 Try Project
  • Android Lollipop:将应用程序小部件添加到主屏幕时启动器崩溃

    添加小部件时 启动器在 Android Lollipop 上崩溃 并显示以下消息 在以前的 Android 版本上运行良好 编辑 这只发生在横向方向 12 16 12 35 10 208 E AndroidRuntime 960 java
  • Android - 从渲染线程内结束活动

    下午好 我不熟悉 android 中的活动生命周期 并且一直在尽可能地阅读 但我不知道如何以良好的方式解决以下问题 我有一个使用 GLSurfaceView 的活动来在屏幕上绘制各种内容 在这个 GLSurfaceView 的渲染线程中 我

随机推荐

  • Vue.js+Vue-router.js实现单页面路由跳转spa(不使用vue脚手架)

    Vue js Vue router js实现单页面路由跳转 不使用vue脚手架 前言 最近在做一个商城项目 想实现单页面路由的跳转 个人中心 侧边栏点击不同名称的跳转不同界面 但是主页面不变 借鉴了他人的项目 实现了此功能 一 文件引入 实
  • QT学习笔记(二)

    模态和非模态对话框 标准对话框和文件对话框 include mainwindow h include ui mainwindow h include
  • Google Maps API v3离线开发包

    http blog 3snews net space php uid 730 do blog id 61654 在09年的时候 我就写过一篇Google Maps API离线开发包 没有网络也可以开发Gmap了 后来liongis大虾又重新
  • Jpa操作数据库之@Query使用SQL语句

    使用Jpa操作数据库除了简单的 save findOne findBy delete 等等还可以使用原生的SQL语句 下面就说一些简单的使用SQL语句操作 首先写一个接口继承 JpaRepository 接口 例如 public inter
  • javaweb题库

    目录 第1章 网页开发基础 第2章 Java Web概述 第3章 HTTP协议 第4章 Servlet基础 第5章 会话及会话技术 第6章 JSP技术 第7章 EL表达式和JSTL 第8章 JavaBean与JSP开发模型 第9章 Serv
  • 隐私和效用不可兼得?隐私保护开辟商业新境地|第1论

    作者 严强 来源 微众银行区块链 话说天下数据 分久必合 合久必分 伴随着计算机软硬件技术的飞速发展 社会整体信息化程度提高 数据的价值逐渐凸显 由此开创了数据汇集 数据提炼 数据变现的信息时代 信息技术商业化日渐深入的同时 数据汇集潜藏的
  • Qt-虚拟键盘

    杂 开发过程中 查阅大量关于虚拟键盘的使用 其中最容易的是使用Qt自带的输入法 但是此法受制于人 其做法 int main int argc char argv 环境 qputenv QT IM MODULE QByteArray qtvi
  • 银河麒麟创建sh脚本快捷方式的方法

    本文旨在将 sh 做成快捷方式放到桌面上 一 将解压后的文件中的 sh 做成快捷方式放到桌面上 1 在桌面打开终端命令行 2 创建 desktop文件 在打开的终端命令行中 输入vim 快捷方式名称 desktop 3 在vim编辑器中按如
  • 如何在Windows 10上下载并安装Linux Bash Shell?

    Bash is the command line interface for Linux distributions like Ubuntu CentOS Debian Mint Kali RedHat Fedora etc Bash pr
  • Opencv的使用小教程3——利用轮廓检测实现二维码定位

    Opencv的使用小教程3 利用轮廓检测实现二维码定位 二维码具有什么特征 实现效果 识别二维码的流程 1 预处理图像 2 寻找轮廓 3 通过寻找到的轮廓确定 回 的位置 4 创建一张新图 并在新图上画出识别到的 回 并连线 5 寻找直角
  • 论文阅读:(ECCV 2022)Simple Baseline for Image Restoration

    Simple Baseline for Image Restoration ECCV 2022 2022 08 26 两个月的时间终于把那个材料完成了 今天一看虽然审核完了还有些小问题 老板没有怪我还说他会去搞定这个事 TAT 我要做老板的
  • 如何利用python处理excel

    利用Python处理Excel数据可以帮助我们更高效地进行数据分析和处理 以下是一些常用的Python库和工具 Pandas Pandas是一个用于数据处理和分析的Python库 它提供了丰富的数据结构和函数 可以方便地读取 清洗 转换和分
  • 存储器IP核生成 非对齐读写 vivado

    存储器制作 含非对齐读写 1 创建ROM 和 RAM IP核 参考马德老师lab0PPT 1 新建一个项目ROM 选择芯片 创建 2 搜索memory generator 3 双击 4 设置好后点击OK width写32 另一个写1024
  • eclipse中文注释缩进异常

    最近更新了eclipse 发现格式化代码后 中文的注释缩进出现了问题 如下图 这个问题 我们可以通过更改字体解决 推荐修改生成支持中文的字体 最简单的方法就是更改成与系统一致 依次点击 Window gt Preferences gt Ge
  • Shell中sort命令使用

    一 sort命令工作原理 sort命令将文件的每一行作为比较对象 通过将不同行进行相互比较 从而得到最终结果 比较原则是从首字符开始 向后依次按ASCII码值进行比较 最后将结果按升序输出 比较前的结果 rocrocket rocrocke
  • java :基本递归(阶乘,斐波那契数列,猴子吃桃,迷宫,汉诺塔,八皇后)

    1 求一个非负数的阶乘 package ex import java util public class ex1 public static void main String args Scanner myscanner new Scann
  • Hive3 启动 提示:com.ctc.wstx.exc.WstxParsingException: Illegal character entity: expansion character

    Windows10 系统启动Hive3 提示如下错误信息 com ctc wstx exc WstxParsingException Illegal character entity expansion character code 0x8
  • 7.全志H3-准备焊接

    上面是我的微信和QQ群 欢迎新朋友的加入 20201203 CPU和DDR已到 20201207 板子到了 开始焊接 20201208 下班继续焊接 发现少了一个料 漏买了 赶紧淘宝补一个 现在就把手上的板子拆了个芯片先用着 焊接完成 测试
  • Partition Pruning和Partition-Wise Joins

    Partition Pruning Partition pruning is an essential performance feature for data warehouses In partition pruning the opt
  • Android Bitmap图像处理(1)- 图片压缩

    一直以来Bitmap都是开发中很棘手的问题 这个问题就是传说中的OOM java lang OutofMemoryError 内存溢出 那么Bitmap为何如此丧失 令无数Android开发者所懊恼 一 Bitmap引发OOM的原因 由于每