发布网友 发布时间:2022-04-23 12:24
共10个回答
热心网友 时间:2023-01-18 22:18
背景
在手机上用户随手拍一张衣服的照片,去找类似图片的需求比较明显,以图搜图项目目的就是满足用户的这部分需求。
该项目初步预计5个类目,每个类目500万图片用于检索。经过特征提取,每张图片可以表示为30976维空间中的一个点,即可以用30976个float值表示,为了便于处理,我们将特征值乘以100000,在不损失float值精度的情况下,用int32_t存储图片特征。
图片检索时需要计算query 图片和索引图片的欧式距离,图片之间计算欧式距离的耗时为50微秒,经过cpu指令集优化(sse),欧式距离计算耗时减少到13微秒。
在压缩之前,所有图片的大小为 3T( 4 * 30k * 25000000),每台机器30G内存用于存储图片,需要100台机器存储全量图片。
需要在计算欧式距离效率不降低的情况下,对图片进行压缩,大规模减少机器的占用。
我们的目标是压缩到500G左右,即压缩之后每张图片20k左右,欧式距离计算耗时为15微秒左右。
欧式距离计算要求耗时在微秒级别,已有的压缩方法,比如p4delta、valgrind压缩等在性能上不满足要求,需要我们根据数据特点自己定制压缩方法。
成果
目前的压缩方法单张图片由120k 压缩到了平均13k。
欧式距离计算平均耗时为9微秒。
这么靠谱的成果是如何做到的呢?
初步尝试
bitmap的方法
观察数据特点,发现平均每张图片有7000个数为非0值,其他值都为 0。首先想到的是用bitmap表示30976个值在特定的位置是否是0。bitmap需要30976 / 8= 4k个字节。然后只存储非0值,需要7k * 4,压缩之后平均每张图片大小为32k。压缩代码大体如下:
int bitmap_len = size / 8 + 8;
uint_t *bitmap = (uint_t*)(cmpr_buf);
int32_t *data = (int32_t*)(cmpr_buf + bitmap_len);
for(unsigned int i=0;i<size;i++) {
if(list[i] != 0) {
data[index++] = list[i];
bitmap[i/] |= bit_mask_tab[i % ];
}
}
但是在计算图片之间的欧式距离时,需要遍历30976次bitmap,并判断特定位的值知否为0,即将bitmap和掩码数组进行与操作,比较耗时,计算耗时在100微秒以上。计算两个压缩图片的欧式距离代码:
for(i=0; i<size/; i++) { for(int j=0; j<; j++) { a = 0; b = 0; if((bitmap1[i] & bit_mask_tab[j])) { a = data1[index1++]; } if((bitmap2[i] & bit_mask_tab[j])) { b = data2[index2++]; } olength += (a - b) * (a - b); } }
采用offset的压缩方式
我们只保存非0数据的off_set和value,off_set最大值30975,需要用int16_t来保存,value的范围0~100万,需要int32_t来表示,采用该方法的话,每个图片占用空间为42k (7k * (2 + 4))。
for(int i=0; i<size; i++) {
if(list[i] != 0) {
index++;
}
}
*(int16_t*) cmpr_buf = index;
int16_t *p_off = (int16_t*)cmpr_buf + 1;
int32_t *p_data = (int32_t*)(((char *)cmpr_buf) + sizeof(int16_t) * index + sizeof(int16_t));
index = 0;
for(int i=0; i<size; i++) {
if(list[i] != 0) {
p_off[index] = i;
p_data[index] = list[i];
index++;
}
}
计算两个压缩图片的欧式距离的时候,采用按照off_set归并的方法:
while(p_data1<end1 && p_data2 < end2){
if(*p_off1 < *p_off2) {
olength += *p_data1 * *p_data1;
p_data1++;
p_off1++;
} else if(*p_off1 > *p_off2) {
olength += *p_data2 * *p_data2;
p_data2++;
p_off2++;
} else {
olength += (*p_data1 - *p_data2) * (*p_data1 - *p_data2);
p_data1++;
p_data2++;
p_off1++;
p_off2++;
}
}
该方法进行欧式距离的耗时为55微秒,我们认为是if 条件比较耗时,于是尝试了用位掩码替代if的方式:
while(p_data1 < end1 && p_data2<end2) {
a = ((*p_off1 - *p_off2) <= 0);
b = ((*p_off2 - *p_off1) <= 0);
tmp1 = -a & *p_data1;
tmp2 = -b & *p_data2;
p_off1 += a;
p_off2 += b;
p_data1 += a;
p_data2 += b;
tmp = tmp1 - tmp2;
olength += tmp * tmp;
}
该方式消除了if 条件判断,但是耗时为70微秒,性能反而下降了,耗时的原因是cpu的指令增多了。
性能优化
场景分析
两个压缩图片计算 --> 一个压缩一个非压缩
目前的优化进入了一个瓶颈,如何才能提升性能到10微秒级别呢?我们回过头来重新考虑了一下应用场景,在线的场景是query图片和一系列图片计算距离,离线的场景是中心点图片和其他一系列图片计算距离也就是说都是一个图片和多个图片进行距离计算,这时一个图片不需要进行压缩,完全可以是非压缩的,即使该图片是压缩也可以先解压计算欧式距离实际上可以转化为一个非压缩图片和多个压缩图片计算欧式距离。对这样的情况,我们需要重新考虑提升效率的问题。
确定采用off_set压缩方式
对于计算一个压缩和一个非压缩图片欧式距离的问题,比较bitmap的压缩方式和off_set的压缩方式,off_set的压缩方式有明显的优势对于bitmap方式,最耗时的地方仍然是访问30976次bitmap,然后做与操作,来获取解压后的值,遍历30976次bitmap耗时,至少50微秒以上但是off_set的方式保存了7000个非0数据的off_set,我们只需要遍历7000次非0 数组就可以计算出欧式距离。
一个压缩一个非压缩
做法
首先计算好非压缩图片的累加平方和,每次查询计算多次欧式距离,只计算一次累加平方和。
遍历压缩图片数组,计算该值和另一张非压缩图片的对应off_set的差值的平方。
对于压缩图片的为0的那些值来说,欧式距离只需要加上非压缩图片那些值的平方和。
举例:
a.非压缩图片:[0 2 3 0 4 0 0 5 6 0 0] ,压缩图片:[0 0 0 6 6 6 0 0 ]
b.事先计算好非压缩图片的特定位之前的所有值的平方和:sqrt[0 4 13 13 29 29 29 54 90 90 90]
c.压缩的数组为 off[3 4 5], data[6 6 6 ]
d.遍历off和data数组
olength += (6 - 0) * (6 - 0) olength += (sqrt[2] - sqrt[0])
olength += (6 - 4) * (6 - 4)olength += (sqrt[3] - sqrt[3])
olength += (6 - 0) * (6 - 0) olength += (sqrt[4] - sqrt[4])
效率:20微秒
该方法只需要遍历7000次数组, 进行7000次相减 平方操作和 7000次访问sqrt 数组操作,大大简化了复杂度。
代码如下:
data1为压缩数据,data2为非压缩数据:
for(int i=0; i<num; i++) {
olength += (data1[i] - data2[off1[i]]) * (data1[i] - data2[off1[i]]);
olength += sqrt[off[i] - 1] - sqrt[off[i-1]];
}
热心网友 时间:2023-01-18 23:36
手机照片怎么压缩200k
时间: 2020-09-07
手机型号:华为P40
系统版本:emui 10.1.0
软件版本:图片裁剪助手 V4.0
手机相片太大,发出去的相片质量不好,那么手机照片怎么压缩200k呢?
1、点击桌面上的图片剪辑助手,点击图片压缩。
2、调整参数,把大小设置成不超过200B,点击选择照片
3、挑选一张照片,点击确定,调整好修剪框,点击√即可。
温馨提示:压缩时还可以选择照片的张数以及长度和宽度。
现在手机的像素越来越高,去年小米还出了一款一亿像素的手机,以前拍一张清楚一些的图片可能只有六七百KB,可是现在用手机拍一张照片三四M是常有的事,有的时候一张照片拍到10M以上也是常有的事情,对于平时经常用手机拍照的小伙伴来说,手机内存可能就不够用了,这个时候就需要用到照片压缩工具了,今天小编就来给大家推荐一款图片压缩器,无需下载任何APP,使用手机就可以对照片进行压缩,下面一起来看看吧。
第一步:首先打开压缩图网站,打开后向下滑动即可看到压缩界面,点击选择图片压缩即可上传图片。
第二步:图片上传以后,可以通过上方菜单栏设置图片的尺寸、宽、高参数以及压缩等级,尺寸、宽、高等参数不设置默认按照原图尺寸进行压缩;压缩等级越低则压缩后的图片体积越小。
第三步:图片压缩完成后,点击保存图片,即可把图片保存至本地。
原本1M多的图片,在经过压缩后尺寸没变,体积仅有200多K,体积降低了70%,这么好用的压缩工具快来试试吧!压缩图不仅支持手机端图片在线压缩,同时也支持电脑端进行图片压缩,电脑端还有批量云端压缩功能,一次最多同时压缩60张图片,简单又实用,快来试试吧!
热心网友 时间:2023-01-19 01:11
付费内容限时免费查看回答亲~相遇是我们的缘分,这道题由我来回答,我正在打字,会需要一点时间,还请您耐心等待一下,不要着急哦,亲。
需要用到美图秀秀软件01
手机图片的大小和像素有关,只要缩小像素自然就会缩小内存大小。
进入美图秀秀APP界面,选择“美化图片”,进入编辑界面,选择“编辑”。
02
点击想要进行处理的图片。
03
进入编辑裁剪界面,根据需求进行裁剪即可,显示的数字即为像素。
04
裁剪完成后,点击右上角“勾”进行保存即可。这样我们会发现手机图片变到200-300kb以内了。
亲,以上就是我给出的回答,如果对您有所帮助,希望您能给我一个赞,赞对我十分重要,在这里先谢谢您了。
热心网友 时间:2023-01-19 03:02
这位朋友,你好,手机图片你可以通过自己的连接电脑传输,然后呢做成压缩文件。
热心网友 时间:2023-01-19 05:10
现在我们还是可以把手机下的图片大大压缩到200k的,并且这样的话我觉得还是通过设置更好的选择吧。
热心网友 时间:2023-01-19 07:35
可以把它传到电脑上,再用Windows自带的画图工具打开,然后在右上角哪里修改像素,把像素调低一点就能得到200k以下的照片了。
热心网友 时间:2023-01-19 10:16
我们把手机图片压缩到200k,这个你找找这专业性的一些解答,或者从网上搜。
热心网友 时间:2023-01-19 13:14
像压缩到200开水可以软软压缩或者直接是复制粘贴可以了,然后是用那个不要用了,高速呀,就可以了,用那个低低保真呢
热心网友 时间:2023-01-19 16:29
有专门的手机照片压缩的软件
热心网友 时间:2023-01-19 20:00
笑一笑,亚瑟人家这样发一个人才能更好的进家族中,应该才开店时用了。