lm opencv 算法_OpenCV进行图像相似度对比的几种办法

// PSNR.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include // Console I/O

#include // String to number conversion

#include // Basic OpenCV structures

#include // Image processing methods for the CPU

#include // Read images

#include // GPU structures and methods

using namespace std;

using namespace cv;

double getPSNR(const Mat& I1, const Mat& I2); // CPU versions

Scalar getMSSIM( const Mat& I1, const Mat& I2);

double getPSNR_GPU(const Mat& I1, const Mat& I2); // Basic GPU versions

Scalar getMSSIM_GPU( const Mat& I1, const Mat& I2);

struct BufferPSNR // Optimized GPU versions

{ // Data allocations are very expensive on GPU. Use a buffer to solve: allocate once reuse later.

gpu::GpuMat gI1, gI2, gs, t1,t2;

gpu::GpuMat buf;

};

double getPSNR_GPU_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b);

struct BufferMSSIM // Optimized GPU versions

{ // Data allocations are very expensive on GPU. Use a buffer to solve: allocate once reuse later.

gpu::GpuMat gI1, gI2, gs, t1,t2;

gpu::GpuMat I1_2, I2_2, I1_I2;

vector<:gpumat> vI1, vI2;

gpu::GpuMat mu1, mu2;

gpu::GpuMat mu1_2, mu2_2, mu1_mu2;

gpu::GpuMat sigma1_2, sigma2_2, sigma12;

gpu::GpuMat t3;

gpu::GpuMat ssim_map;

gpu::GpuMat buf;

};

Scalar getMSSIM_GPU_optimized( const Mat& i1, const Mat& i2, BufferMSSIM& b);

void help()

{

cout

<< "\n--------------------------------------------------------------------------" << endl

<< "This program shows how to port your CPU code to GPU or write that from scratch." << endl

<< "You can see the performance improvement for the similarity check methods (PSNR and SSIM)." << endl

<< "Usage:" << endl

<< "./gpu-basics-similarity referenceImage comparedImage numberOfTimesToRunTest(like 10)." << endl

<< "--------------------------------------------------------------------------" << endl

<< endl;

}

int main(int argc, char *argv[])

{

help();

Mat I1 = imread("swan1.jpg",1); // Read the two images

Mat I2 = imread("swan2.jpg",1);

if (!I1.data || !I2.data) // Check for success

{

cout << "Couldn't read the image";

return 0;

}

BufferPSNR bufferPSNR;

BufferMSSIM bufferMSSIM;

int TIMES;

stringstream sstr("500");

sstr >> TIMES;

double time, result;

//------------------------------- PSNR CPU ----------------------------------------------------

time = (double)getTickCount();

for (int i = 0; i < TIMES; ++i)

result = getPSNR(I1,I2);

time = 1000*((double)getTickCount() - time)/getTickFrequency();

time /= TIMES;

cout << "Time of PSNR CPU (averaged for " << TIMES << " runs): " << time << " milliseconds."

<< " With result of: " << result << endl;

------------------------------- PSNR GPU ----------------------------------------------------

//time = (double)getTickCount();

//for (int i = 0; i < TIMES; ++i)

// result = getPSNR_GPU(I1,I2);

//time = 1000*((double)getTickCount() - time)/getTickFrequency();

//time /= TIMES;

//cout << "Time of PSNR GPU (averaged for " << TIMES << " runs): " << time << " milliseconds."

// << " With result of: " << result << endl;

/*

//------------------------------- PSNR GPU Optimized--------------------------------------------

time = (double)getTickCount(); // Initial call

result = getPSNR_GPU_optimized(I1, I2, bufferPSNR);

time = 1000*((double)getTickCount() - time)/getTickFrequency();

cout << "Initial call GPU optimized: " << time <

<< " With result of: " << result << endl;

time = (double)getTickCount();

for (int i = 0; i < TIMES; ++i)

result = getPSNR_GPU_optimized(I1, I2, bufferPSNR);

time = 1000*((double)getTickCount() - time)/getTickFrequency();

time /= TIMES;

cout << "Time of PSNR GPU OPTIMIZED ( / " << TIMES << " runs): " << time

<< " milliseconds." << " With result of: " << result << endl << endl;

//------------------------------- SSIM CPU -----------------------------------------------------

Scalar x;

time = (double)getTickCount();

for (int i = 0; i < TIMES; ++i)

x = getMSSIM(I1,I2);

time = 1000*((double)getTickCount() - time)/getTickFrequency();

time /= TIMES;

cout << "Time of MSSIM CPU (averaged for " << TIMES << " runs): " << time << " milliseconds."

<< " With result of B" << x.val[0] << " G" << x.val[1] << " R" << x.val[2] << endl;

//------------------------------- SSIM GPU -----------------------------------------------------

time = (double)getTickCount();

for (int i = 0; i < TIMES; ++i)

x = getMSSIM_GPU(I1,I2);

time = 1000*((double)getTickCount() - time)/getTickFrequency();

time /= TIMES;

cout << "Time of MSSIM GPU (averaged for " << TIMES << " runs): " << time << " milliseconds."

<< " With result of B" << x.val[0] << " G" << x.val[1] << " R" << x.val[2] << endl;

//------------------------------- SSIM GPU Optimized--------------------------------------------

time = (double)getTickCount();

x = getMSSIM_GPU_optimized(I1,I2, bufferMSSIM);

time = 1000*((double)getTickCount() - time)/getTickFrequency();

cout << "Time of MSSIM GPU Initial Call " << time << " milliseconds."

<< " With result of B" << x.val[0] << " G" << x.val[1] << " R" << x.val[2] << endl;

time = (double)getTickCount();

for (int i = 0; i < TIMES; ++i)

x = getMSSIM_GPU_optimized(I1,I2, bufferMSSIM);

time = 1000*((double)getTickCount() - time)/getTickFrequency();

time /= TIMES;

cout << "Time of MSSIM GPU OPTIMIZED ( / " << TIMES << " runs): " << time << " milliseconds."

<< " With result of B" << x.val[0] << " G" << x.val[1] << " R" << x.val[2] << endl << endl;

return 0;

*/

getchar();

}

double getPSNR(const Mat& I1, const Mat& I2)

{

Mat s1;

absdiff(I1, I2, s1); // |I1 - I2|

s1.convertTo(s1, CV_32F); // cannot make a square on 8 bits

s1 = s1.mul(s1); // |I1 - I2|^2

Scalar s = sum(s1); // sum elements per channel

double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels

if( sse <= 1e-10) // for small values return zero

return 0;

else

{

double mse =sse /(double)(I1.channels() * I1.total());

double psnr = 10.0*log10((255*255)/mse);

return psnr;

}

}

double getPSNR_GPU_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b)

{

b.gI1.upload(I1);

b.gI2.upload(I2);

b.gI1.convertTo(b.t1, CV_32F);

b.gI2.convertTo(b.t2, CV_32F);

gpu::absdiff(b.t1.reshape(1), b.t2.reshape(1), b.gs);

gpu::multiply(b.gs, b.gs, b.gs);

double sse = gpu::sum(b.gs, b.buf)[0];

if( sse <= 1e-10) // for small values return zero

return 0;

else

{

double mse = sse /(double)(I1.channels() * I1.total());

double psnr = 10.0*log10((255*255)/mse);

return psnr;

}

}

double getPSNR_GPU(const Mat& I1, const Mat& I2)

{

gpu::GpuMat gI1, gI2, gs, t1,t2;

gI1.upload(I1);

gI2.upload(I2);

gI1.convertTo(t1, CV_32F);

gI2.convertTo(t2, CV_32F);

gpu::absdiff(t1.reshape(1), t2.reshape(1), gs);

gpu::multiply(gs, gs, gs);

Scalar s = gpu::sum(gs);

double sse = s.val[0] + s.val[1] + s.val[2];

if( sse <= 1e-10) // for small values return zero

return 0;

else

{

double mse =sse /(double)(gI1.channels() * I1.total());

double psnr = 10.0*log10((255*255)/mse);

return psnr;

}

}

Scalar getMSSIM( const Mat& i1, const Mat& i2)

{

const double C1 = 6.5025, C2 = 58.5225;

/***************************** INITS **********************************/

int d = CV_32F;

Mat I1, I2;

i1.convertTo(I1, d); // cannot calculate on one byte large values

i2.convertTo(I2, d);

Mat I2_2 = I2.mul(I2); // I2^2

Mat I1_2 = I1.mul(I1); // I1^2

Mat I1_I2 = I1.mul(I2); // I1 * I2

/*************************** END INITS **********************************/

Mat mu1, mu2; // PRELIMINARY COMPUTING

GaussianBlur(I1, mu1, Size(11, 11), 1.5);

GaussianBlur(I2, mu2, Size(11, 11), 1.5);

Mat mu1_2 = mu1.mul(mu1);

Mat mu2_2 = mu2.mul(mu2);

Mat mu1_mu2 = mu1.mul(mu2);

Mat sigma1_2, sigma2_2, sigma12;

GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);

sigma1_2 -= mu1_2;

GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);

sigma2_2 -= mu2_2;

GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);

sigma12 -= mu1_mu2;

/ FORMULA

Mat t1, t2, t3;

t1 = 2 * mu1_mu2 + C1;

t2 = 2 * sigma12 + C2;

t3 = t1.mul(t2); // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))

t1 = mu1_2 + mu2_2 + C1;

t2 = sigma1_2 + sigma2_2 + C2;

t1 = t1.mul(t2); // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))

Mat ssim_map;

divide(t3, t1, ssim_map); // ssim_map = t3./t1;

Scalar mssim = mean( ssim_map ); // mssim = average of ssim map

return mssim;

}

Scalar getMSSIM_GPU( const Mat& i1, const Mat& i2)

{

const float C1 = 6.5025f, C2 = 58.5225f;

/***************************** INITS **********************************/

gpu::GpuMat gI1, gI2, gs1, t1,t2;

gI1.upload(i1);

gI2.upload(i2);

gI1.convertTo(t1, CV_MAKE_TYPE(CV_32F, gI1.channels()));

gI2.convertTo(t2, CV_MAKE_TYPE(CV_32F, gI2.channels()));

vector<:gpumat> vI1, vI2;

gpu::split(t1, vI1);

gpu::split(t2, vI2);

Scalar mssim;

for( int i = 0; i < gI1.channels(); ++i )

{

gpu::GpuMat I2_2, I1_2, I1_I2;

gpu::multiply(vI2[i], vI2[i], I2_2); // I2^2

gpu::multiply(vI1[i], vI1[i], I1_2); // I1^2

gpu::multiply(vI1[i], vI2[i], I1_I2); // I1 * I2

/*************************** END INITS **********************************/

gpu::GpuMat mu1, mu2; // PRELIMINARY COMPUTING

gpu::GaussianBlur(vI1[i], mu1, Size(11, 11), 1.5);

gpu::GaussianBlur(vI2[i], mu2, Size(11, 11), 1.5);

gpu::GpuMat mu1_2, mu2_2, mu1_mu2;

gpu::multiply(mu1, mu1, mu1_2);

gpu::multiply(mu2, mu2, mu2_2);

gpu::multiply(mu1, mu2, mu1_mu2);

gpu::GpuMat sigma1_2, sigma2_2, sigma12;

gpu::GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);

//sigma1_2 = sigma1_2 - mu1_2;

gpu::subtract(sigma1_2,mu1_2,sigma1_2);

gpu::GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);

//sigma2_2 = sigma2_2 - mu2_2;

gpu::GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);

(Mat)sigma12 =(Mat)sigma12 - (Mat)mu1_mu2;

//sigma12 = sigma12 - mu1_mu2

/ FORMULA

gpu::GpuMat t1, t2, t3;

// t1 = 2 * mu1_mu2 + C1;

// t2 = 2 * sigma12 + C2;

// gpu::multiply(t1, t2, t3); // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))

//

// t1 = mu1_2 + mu2_2 + C1;

// t2 = sigma1_2 + sigma2_2 + C2;

// gpu::multiply(t1, t2, t1); // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))

gpu::GpuMat ssim_map;

gpu::divide(t3, t1, ssim_map); // ssim_map = t3./t1;

Scalar s = gpu::sum(ssim_map);

mssim.val[i] = s.val[0] / (ssim_map.rows * ssim_map.cols);

}

return mssim;

}

Scalar getMSSIM_GPU_optimized( const Mat& i1, const Mat& i2, BufferMSSIM& b)

{

int cn = i1.channels();

const float C1 = 6.5025f, C2 = 58.5225f;

/***************************** INITS **********************************/

b.gI1.upload(i1);

b.gI2.upload(i2);

gpu::Stream stream;

stream.enqueueConvert(b.gI1, b.t1, CV_32F);

stream.enqueueConvert(b.gI2, b.t2, CV_32F);

gpu::split(b.t1, b.vI1, stream);

gpu::split(b.t2, b.vI2, stream);

Scalar mssim;

for( int i = 0; i < b.gI1.channels(); ++i )

{

gpu::multiply(b.vI2[i], b.vI2[i], b.I2_2, stream); // I2^2

gpu::multiply(b.vI1[i], b.vI1[i], b.I1_2, stream); // I1^2

gpu::multiply(b.vI1[i], b.vI2[i], b.I1_I2, stream); // I1 * I2

//gpu::GaussianBlur(b.vI1[i], b.mu1, Size(11, 11), 1.5, 0, BORDER_DEFAULT, -1, stream);

//gpu::GaussianBlur(b.vI2[i], b.mu2, Size(11, 11), 1.5, 0, BORDER_DEFAULT, -1, stream);

gpu::multiply(b.mu1, b.mu1, b.mu1_2, stream);

gpu::multiply(b.mu2, b.mu2, b.mu2_2, stream);

gpu::multiply(b.mu1, b.mu2, b.mu1_mu2, stream);

//gpu::GaussianBlur(b.I1_2, b.sigma1_2, Size(11, 11), 1.5, 0, BORDER_DEFAULT, -1, stream);

//gpu::subtract(b.sigma1_2, b.mu1_2, b.sigma1_2, stream);

//b.sigma1_2 -= b.mu1_2; - This would result in an extra data transfer operation

//gpu::GaussianBlur(b.I2_2, b.sigma2_2, Size(11, 11), 1.5, 0, BORDER_DEFAULT, -1, stream);

//gpu::subtract(b.sigma2_2, b.mu2_2, b.sigma2_2, stream);

//b.sigma2_2 -= b.mu2_2;

//gpu::GaussianBlur(b.I1_I2, b.sigma12, Size(11, 11), 1.5, 0, BORDER_DEFAULT, -1, stream);

//gpu::subtract(b.sigma12, b.mu1_mu2, b.sigma12, stream);

//b.sigma12 -= b.mu1_mu2;

//here too it would be an extra data transfer due to call of operator*(Scalar, Mat)

gpu::multiply(b.mu1_mu2, 2, b.t1, stream); //b.t1 = 2 * b.mu1_mu2 + C1;

//gpu::add(b.t1, C1, b.t1, stream);

gpu::multiply(b.sigma12, 2, b.t2, stream); //b.t2 = 2 * b.sigma12 + C2;

//gpu::add(b.t2, C2, b.t2, stream);

gpu::multiply(b.t1, b.t2, b.t3, stream); // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))

//gpu::add(b.mu1_2, b.mu2_2, b.t1, stream);

//gpu::add(b.t1, C1, b.t1, stream);

//gpu::add(b.sigma1_2, b.sigma2_2, b.t2, stream);

//gpu::add(b.t2, C2, b.t2, stream);

gpu::multiply(b.t1, b.t2, b.t1, stream); // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))

gpu::divide(b.t3, b.t1, b.ssim_map, stream); // ssim_map = t3./t1;

stream.waitForCompletion();

Scalar s = gpu::sum(b.ssim_map, b.buf);

mssim.val[i] = s.val[0] / (b.ssim_map.rows * b.ssim_map.cols);

}

return mssim;

}

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

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

相关文章

android程序获取WIFI的IP地址和MAC地址

转自&#xff1a;http://my.oschina.net/chenj/blog/68680 近日在鼓捣这玩意&#xff0c;拿出来大家分享一下&#xff0c;代码比较简单&#xff0c;如果有不懂的再问 <Button android:id"id/btn"android:text"获取IP"android:layout_width"fill_pa…

计算机d,计算机词汇d

data block 数据块data connection 数据连接Data Control Language (DCL) 数据控制语言 (DCL)data definition 数据定义data definition language (DDL) 数据定义语言 (DDL)data dictionary 数据字典data dictionary view 数据字典视图data explosion 数据爆炸data file 数据文…

a5d2 mac 驱动分析

2.6内核以后的多数驱动都是基于平台总线驱动模型(platform)&#xff0c;对于平台总线来说&#xff0c;无非是两块组成 platform_driver和platform_device&#xff0c;在a5d2的bsp中&#xff0c;因为引入了device tree&#xff0c;因此&#xff0c;代码里已经看不到 platform_…

10以内的分解与组成怎么教_【一年级数学】(上)10以内的分与合技巧及练习题...

《10以内的分与合》知识点数的组成&#xff1a;一个数(1除外)分成几和几&#xff0c;先把这个数分成1和几&#xff0c;依次分到几和1为止。例如&#xff1a;5的组成有1和4、2和3、3和2、4和1。把一个数分成几和几时&#xff0c;要有序地进行分解&#xff0c;防止重复或遗漏。《…

linux下swftools 的配置

1、安装所需的库和组件。机器之前安装过了&#xff0c;主要安装的是下面几个组件。如果不安装会提示machine x86_64-unknown-linux not recognizedyum install gcc* automake zlib-devel libjpeg-devel giflib-devel freetype-devel2、下载编译安装swftools。wget http://www.s…

交通与计算机杂志社,交通信息与安全

期刊名称&#xff1a;交通信息与安全主管单位&#xff1a;中华人民共和国教育部主办单位&#xff1a;武汉理工大学;交通计算机应用信息网期刊级别&#xff1a;国家级国际刊号&#xff1a;ISSN&#xff1a;1674-4861国内刊号&#xff1a;CN&#xff1a;42-1781/U邮发代号&#x…

k1658停运到什么时候_最近网传的春节快递停运时间表,是假的!

“我有货&#xff0c;你有钱&#xff0c;其间没有快递员。”最近&#xff0c;杭州市民梁先生的朋友圈里&#xff0c;突然火了一张图片。标记为2019年日历的这张图片上&#xff0c;1月25日和2月12日之间的日期都被白线框定&#xff0c;并打出了“其间没有快递员”的字样。还有一…

a5d2 phy驱动

1. 下面代码实现了phy驱动的实现和注册 2. device tree实现了phy的device 3. 在mdio总线注册后&#xff0c;总线会调用总线驱动的match函数&#xff0c;进行device和driver的匹配 static int mdio_bus_match(struct device *dev, struct device_driver *drv) return (phydrv-…

vs2008配置winddk

Vs2008配置winddk 1、 安装winddk&#xff0c;我安装在了c盘下&#xff1b; 2、 电脑-》属性-》环境配置里 系统变量里加入 DDKBASE&#xff0c;其值是 3、 path变量里增加 ;C:\WinDDK\7600.16385.1; 第二大步&#xff1a;&#xff08;非常关键&#xff09; 1、 vs2008里 工具…

android跨进程事件注入(程序模拟用户输入)

转载请注明出处 早想写这篇&#xff0c;一直没空&#xff0c;现在总结下。 需求&#xff1a; 需要在程序内模拟用户输入&#xff0c;比如点击屏幕&#xff0c;或者输入键盘。模拟用户的滑动等。具体的需求&#xff0c;比如测试的时候&#xff0c;测试打开浏览器1000次。或者通过…

三菱d700变频器接线图_图解PLC与变频器通讯接线

plc与变频器两者是一种包含与被包含的关系&#xff0c;PLC与变频器都可以完成一些特定的指令&#xff0c;用来控制电机马达&#xff0c;PLC是一种程序输入执行硬件&#xff0c;变频器则是其中之一。但是PLC的涵盖范围又比变频器大&#xff0c;还可以用来控制更多的东西&#xf…

全国高校计算机考试用的什么版本,全国高校计算机等级考试与全国计算机等级考试,有区别吗...

技校网专门为您推荐的类似问题答案问题1&#xff1a;全国高校计算机等级考试一级和全国计算机等级考试一级有什么区别不一样的 全国高校计算机等级考试是专门为全国各高校非计算机专业的在校大学生举行的计算机基础知识和应用能力等级考试。根据教育厅通知要求&#xff0c;各高…

ASCII码排序

ASCII码排序 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;2描述输入三个字符&#xff08;可以重复&#xff09;后&#xff0c;按各字符的ASCII码从小到大的顺序输出这三个字符。输入第一行输入一个数N,表示有N组测试数据。后面的N行输入多组…

a5d2启动分析

A5D2对外部存储设备的启动顺序如下图&#xff1a; SDMMC_1接的sd卡&#xff0c;SDMMC_0接的emmc, SPI_0接的串行flash,当外部存储都不可用或没有启动程序的话&#xff0c;会直接进入sam-ba monitor&#xff0c;就可以执行sam-ba提供的各种烧写脚本了。 目前我们使用的烧写脚本…

软件测试菲律宾,英雄联盟手游菲律宾测试资格怎么得 菲律宾测试资格获取攻略[多图]...

英雄联盟手游菲律宾服务器将先行开放测试&#xff0c;所有想体验游戏的玩家可以申请获得测试资格来优先体验&#xff0c;下面各位玩家一起来看一下测试资格的获取方法吧。目前游戏只能够在外服测试&#xff0c;而且是菲律宾的服务器才行&#xff0c;这是国外游戏测试的一个老套…

ug建模文本怎么竖着_UG建模知乎答疑练习小集锦

持续更新中……solidworks 如何在圆弧边折弯&#xff1f;​www.zhihu.comsolidworks像这样使用扫描为什么得不到结果&#xff1f;​www.zhihu.com请问一下solidworks像我这样使用扫描加了引导线但为什么没有反应&#xff08;想扫描一个杨桃那样的东西&#xff09;?​www.zhihu…

NSHashTable and NSMapTable

NSSet和NSDictionary是两个常用的类&#xff0c;但是他们默认假定了其中对象的内存行为。对于NSSet&#xff0c;object是强引用的&#xff0c;和NSDictionary中的value是一样的。而NSDictionary中的key则是copy的&#xff0c;因此当开发者想要使NSSet的objects或者NSDictionary…

linux中 likely与unlikely

看内核时总遇到if(likely( )){}或是if(unlikely( ))这样的语句&#xff0c;最初不解其意&#xff0c;现在有所了解&#xff0c;所以也想介绍一下。likely() 与 unlikely()是内核&#xff08;我看的是2.6.22.6版本&#xff0c;2.6的版本应该都有&#xff09;中定义的两个宏。位于…

win10 iis网站服务器,windows10如何搭建IIS服务器

web服务器无处不在&#xff0c;本次教程主要简单介绍一个简单的web服务IIS&#xff0c;IIS主要适用于ASP.NET、ASP等语言使用。1、打开控制面选择程序和功能2、点击启用或关闭windows功能打开一个小框框提供给用户配置相关软件&#xff0c;本次主要打开IIS功能 &#xff0c;具体…

表格数字乘以百分比怎么算_EXCEL记住这两个快捷键,1秒种设好数字格式

你还在用右键设置单元格格式来设置千分位吗&#xff1f;你还在用右键设置单元格格式来设置百分比吗&#xff1f;今天小马教大家两个快捷键&#xff0c;记住这两个快捷键&#xff0c;1秒钟设好数字格式。设置数字的千分位 CtrlShift1可能这个数字比较难记&#xff0c;可以把1想象…