HarmonyOS开发案例:【图片编辑】

介绍

本篇Codelab是基于ArkTS的声明式开发范式的样例,主要介绍了图片编辑实现过程。样例主要包含以下功能:

  1. 图片的解码。
  2. 使用PixelMap进行图片编辑,如裁剪、旋转、亮度、透明度、饱和度等。
  3. 图片的编码。

相关概念

  • [图片解码]:读取不同格式的图片文件,无压缩的解码为位图格式。
  • [PixelMap]:图片解码后的状态,用于对图片像素进行处理。
  • [图片编码]:图片经过像素处理完成之后,需要重新进行编码打包,生成需要的图片格式。

环境搭建

软件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:[润和RK3568开发板]。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. [获取OpenHarmony系统版本]:标准系统解决方案(二进制)。以3.2 Release版本为例:

  2. 搭建烧录环境。

    1. [完成DevEco Device Tool的安装]
    2. [完成RK3568开发板的烧录]
  3. 搭建开发环境。

    1. 开始前请参考[工具准备],完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考[使用工程向导]创建工程(模板选择“Empty Ability”)。
    3. 工程创建完成后,选择使用[真机进行调测]。
    4. HarmonyOS与OpenHarmony鸿蒙文档籽料:mau123789是v直接拿

搜狗高速浏览器截图20240326151450.png

代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在gitee中提供。

├──entry/src/main/ets                            // 代码区
│  ├──common                         
│  │  └──constant
│  │     └──CommonConstant.ets                   // 常量类
│  ├──entryability
│  │  └──EntryAbility.ts                         // 本地启动ability           
│  ├──pages
│  │  └──HomePage.ets                            // 本地主页面    
│  ├──utils
│  │  ├──AdjustUtil.ets                          // 调节工具类
│  │  ├──CropUtil.ets                            // 裁剪工具类
│  │  ├──DecodeUtil.ets                          // 解码工具类
│  │  ├──DrawingUtils.ets                        // Canvas画图工具类
│  │  ├──EncodeUtil.ets                          // 编码工具类
│  │  ├──LoggerUtil.ets                          // 日志工具类
│  │  ├──MathUtils.ets                           // 坐标转换工具类
│  │  └──OpacityUtil.ets                         // 透明度调节工具类
│  ├──view
│  │  ├──AdjustContentView.ets                   // 色域调整视图     
│  │  └──ImageSelect.ets                         // Canvas选择框实现类   
│  ├──viewmodel
│  │  ├──CropShow.ets                            // 选择框显示控制类
│  │  ├──CropType.ets                            // 按比例选取图片
│  │  ├──IconListViewModel.ets                   // icon数据
│  │  ├──ImageEditCrop.ets                       // 图片编辑操作类
│  │  ├──ImageFilterCrop.ets                     // 图片操作收集类
│  │  ├──ImageSizeItem.ets                       // 图片尺寸
│  │  ├──Line.ets                                // 线封装类
│  │  ├──MessageItem.ets                         // 多线程封装消息
│  │  ├──OptionViewModel.ets                     // 图片处理封装类
│  │  ├──PixelMapWrapper.ets                     // PixelMap封装类
│  │  ├──Point.ets                               // 点封装类
│  │  ├──Ratio.ets                               // 比例封装类
│  │  ├──Rect.ets                                // 矩形封装类
│  │  ├──RegionItem.ets                          // 区域封装类
│  │  └──ScreenManager.ts                        // 屏幕尺寸计算工具类
│  └──workers
│     ├──AdjustBrightnessWork.ts                 // 亮度异步调节
│     └──AdjustSaturationWork.ts                 // 饱和度异步调节
└──entry/src/main/resources                      // 资源文件目录

鸿蒙开发指导文档:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。

图片解码

在这个章节中,需要完成图片解码的操作,并将解码后的图片展示。效果如图所示:

在进行图片编辑前需要先加载图片,当前文档是在生命周期aboutToAppear开始加载。具体实现步骤。

  1. 读取资源文件。
  2. 将获取的fd创建成图片实例,通过实例获取其pixelMap。
  3. 将解析好的pixelMap通过Image组件加载显示。
// HomePage.ets
aboutToAppear() {this.pixelInit();...
}build() {Column() {...Column() {if (this.isCrop && this.showCanvas && this.statusBar > 0) {if (this.isSaveFresh) {ImageSelect({statusBar: this.statusBar})}...} else {if (this.isPixelMapChange) {Image(this.pixelMap).scale({ x: this.imageScale, y: this.imageScale, z: 1 }).objectFit(ImageFit.None)}...}}...}...
}async getResourceFd(filename: string) {const resourceMgr = getContext(this).resourceManager;const context = getContext(this);if (filename === CommonConstants.RAW_FILE_NAME) {let imageBuffer = await resourceMgr.getMediaContent($r("app.media.ic_low"))let filePath = context.cacheDir + '/' + filename;let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);let writeLen = fs.writeSync(file.fd, imageBuffer.buffer);fs.copyFileSync(filePath, context.cacheDir + '/' + CommonConstants.RAW_FILE_NAME_TEST);return file.fd;} else {let filePath = context.cacheDir + '/' + filename;let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);return file.fd;}
}async getPixelMap(fileName: string) {const fd = await this.getResourceFd(fileName);const imageSourceApi = image.createImageSource(fd);if (!imageSourceApi) {Logger.error(TAG, 'imageSourceAPI created failed!');return;}const pixelMap = await imageSourceApi.createPixelMap({editable: true});return pixelMap;
}

图片处理

当前章节需要完成图片的裁剪、旋转、色域调节(本章只介绍亮度、透明度、饱和度)等功能。

  • 裁剪:选取图片中的部分进行裁剪生成新的图片。

  • 旋转:将图片按照不同的角度进行旋转,生成新的图片。

  • 色域调节:当前Codelab色域调节的亮度、透明度和饱和度,使用色域模型RGB-HSV来实现的。

    • RGB:是我们接触最多的颜色空间,分别为红色®,绿色(G)和蓝色(B)。

    • HSV:是用色相H,饱和度S,明亮度V来描述颜色的变化。

      • H:色相H取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。
      • S:饱和度S越高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
      • V:明度V表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
// AdjustUtil.ets
// rgb转hsv
function rgb2hsv(red: number, green: number, blue: number) {let hsvH: number = 0, hsvS: number = 0, hsvV: number = 0;const rgbR: number = colorTransform(red);const rgbG: number = colorTransform(green);const rgbB: number = colorTransform(blue);const maxValue = Math.max(rgbR, Math.max(rgbG, rgbB));const minValue = Math.min(rgbR, Math.min(rgbG, rgbB));hsvV = maxValue * CommonConstants.CONVERT_INT;if (maxValue === 0) {hsvS = 0;} else {hsvS = Number((1 - minValue / maxValue).toFixed(CommonConstants.DECIMAL_TWO)) * CommonConstants.CONVERT_INT;}if (maxValue === minValue) {hsvH = 0;}if (maxValue === rgbR && rgbG >= rgbB) {hsvH = Math.floor(CommonConstants.ANGLE_60 * ((rgbG - rgbB) / (maxValue - minValue)));}if (maxValue === rgbR && rgbG < rgbB) {hsvH = Math.floor(CommonConstants.ANGLE_60 * ((rgbG - rgbB) / (maxValue - minValue)) + CommonConstants.ANGLE_360);}if (maxValue === rgbG) {hsvH = Math.floor(CommonConstants.ANGLE_60 * ((rgbB - rgbR) / (maxValue - minValue)) + CommonConstants.ANGLE_120);}if (maxValue === rgbB) {hsvH = Math.floor(CommonConstants.ANGLE_60 * ((rgbR - rgbG) / (maxValue - minValue)) + CommonConstants.ANGLE_240);}return [hsvH, hsvS, hsvV];
}
// hsv转rgb
function hsv2rgb(hue: number, saturation: number, value: number) {let rgbR: number = 0, rgbG: number = 0, rgbB: number = 0;if (saturation === 0) {rgbR = rgbG = rgbB = Math.round((value * CommonConstants.COLOR_LEVEL_MAX) / CommonConstants.CONVERT_INT);return { rgbR, rgbG, rgbB };}const cxmC = (value * saturation) / (CommonConstants.CONVERT_INT * CommonConstants.CONVERT_INT);const cxmX = cxmC * (1 - Math.abs((hue / CommonConstants.ANGLE_60) % CommonConstants.MOD_2 - 1));const cxmM = (value - cxmC * CommonConstants.CONVERT_INT) / CommonConstants.CONVERT_INT;const hsvHRange = Math.floor(hue / CommonConstants.ANGLE_60);switch (hsvHRange) {case AngelRange.ANGEL_0_60:rgbR = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbG = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbB = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;break;case AngelRange.ANGEL_60_120:rgbR = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbG = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbB = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;break;case AngelRange.ANGEL_120_180:rgbR = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbG = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbB = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;break;case AngelRange.ANGEL_180_240:rgbR = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbG = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbB = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;break;case AngelRange.ANGEL_240_300:rgbR = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbG = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbB = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;break;case AngelRange.ANGEL_300_360:rgbR = (cxmC + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbG = (0 + cxmM) * CommonConstants.COLOR_LEVEL_MAX;rgbB = (cxmX + cxmM) * CommonConstants.COLOR_LEVEL_MAX;break;default:break;}return [Math.round(rgbR),Math.round(rgbG),Math.round(rgbB)];
}

图片裁剪

  1. 通过pixelMap获取图片尺寸,为后续裁剪做准备。
  2. 确定裁剪的方式,当前裁剪默认有自由选取、1:1选取、4:3选取、16:9选取。
  3. 通过pixelMap调用接口crop()进行裁剪操作。

说明: 当前裁剪功能采用pixelMap裁剪能力直接做切割,会有叠加效果,后续会通过增加选取框对当前功能进行优化。

// HomePage.ets
cropImage(index: CropType) {this.currentCropIndex = index;switch (this.currentCropIndex) {case CropType.ORIGINAL_IMAGE:this.cropRatio = CropRatioType.RATIO_TYPE_FREE;break;case CropType.SQUARE:this.cropRatio = CropRatioType.RATIO_TYPE_1_1;break;case CropType.BANNER:this.cropRatio = CropRatioType.RATIO_TYPE_4_3;break;case CropType.RECTANGLE:this.cropRatio = CropRatioType.RATIO_TYPE_16_9;break;default:this.cropRatio = CropRatioType.RATIO_TYPE_FREE;break;}
}// ImageFilterCrop.ets
cropImage(pixelMap: PixelMapWrapper, realCropRect: RectF, callback: () => void) {let offWidth = realCropRect.getWidth();let offHeight = realCropRect.getHeight();if (pixelMap.pixelMap!== undefined) {pixelMap.pixelMap.crop({size:{ height: vp2px(offHeight), width: vp2px(offWidth) },x: vp2px(realCropRect.left),y: vp2px(realCropRect.top)}, callback);}
}

图片旋转

  1. 确定旋转方向,当前支持顺时针和逆时针旋转。
  2. 通过pixelMap调用接口rotate()进行旋转操作。

// HomePage.ets
rotateImage(rotateType: RotateType) {if (rotateType === RotateType.CLOCKWISE) {try {if (this.pixelMap !== undefined) {this.pixelMap.rotate(CommonConstants.CLOCK_WISE).then(() => {this.flushPixelMapNew();})}} catch (error) {Logger.error(TAG, `there is a error in rotate process with ${error?.code}`);}}if (rotateType === RotateType.ANTI_CLOCK) {try {if (this.pixelMap !== undefined) {this.pixelMap.rotate(CommonConstants.ANTI_CLOCK).then(() => {this.flushPixelMapNew();})}} catch (error) {Logger.error(TAG, `there is a error in rotate process with ${error?.code}`);}}
}

亮度调节

  1. 将pixelMap转换成ArrayBuffer。
  2. 将生成好的ArrayBuffer发送到worker线程。
  3. 对每一个像素点的亮度值按倍率计算。
  4. 将计算好的ArrayBuffer发送回主线程。
  5. 将ArrayBuffer写入pixelMap,刷新UI。

说明: 当前亮度调节是在UI层面实现的,未实现细节优化算法,只做简单示例。调节后的图片会有色彩上的失真。

// AdjustContentView.ets
// 转化成pixelMap及发送buffer到worker,返回数据刷新ui
postToWorker(type: AdjustId, value: number, workerName: string) {let sliderValue = type === AdjustId.BRIGHTNESS ? this.brightnessLastSlider : this.saturationLastSlider;try {let workerInstance = new worker.ThreadWorker(workerName);const bufferArray = new ArrayBuffer(this.pixelMap.getPixelBytesNumber());this.pixelMap.readPixelsToBuffer(bufferArray).then(() => {let message = new MessageItem(bufferArray, sliderValue, value);workerInstance.postMessage(message);if (this.postState) {this.deviceListDialogController.open();}this.postState = false;workerInstance.onmessage = (event: MessageEvents) => {this.updatePixelMap(event)};if (type === AdjustId.BRIGHTNESS) {this.brightnessLastSlider = Math.round(value);} else {this.saturationLastSlider = Math.round(value);}workerInstance.onexit = () => {if (workerInstance !== undefined) {workerInstance.terminate();}}});} catch (error) {Logger.error(`Create work instance fail, error message: ${JSON.stringify(error)}`)}
}// AdjustBrightnessWork.ts
// worker线程处理部分
workerPort.onmessage = function(event : MessageEvents) {let bufferArray = event.data.buf;let last = event.data.last;let cur = event.data.cur;let buffer = adjustImageValue(bufferArray, last, cur);workerPort.postMessage(buffer);workerPort.close();
}// AdjustUtil.ets
// 倍率计算部分
export function adjustImageValue(bufferArray: ArrayBuffer, last: number, cur: number) {return execColorInfo(bufferArray, last, cur, HSVIndex.VALUE);
}

透明度调节

  1. 获取pixelMap。
  2. 调用接口opacity()进行透明度调节。

// OpacityUtil.ets
export async function adjustOpacity(pixelMap: PixelMap, value: number) {if (!pixelMap) {return;}const newPixelMap = pixelMap;await newPixelMap.opacity(value / CommonConstants.SLIDER_MAX);return newPixelMap;
}

饱和度调节

  1. 将pixelMap转换成ArrayBuffer。
  2. 将生成好的ArrayBuffer发送到worker线程。
  3. 对每一个像素点的饱和度按倍率计算。
  4. 将计算好的ArrayBuffer发送回主线程。
  5. 将ArrayBuffer写入pixelMap,刷新UI。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 说明: 当前饱和度调节是在UI层面实现的,未实现细节优化算法,只做简单示例。调节后的图片会有色彩上的失真。

// AdjustContentView.ets
// 转化成pixelMap及发送buffer到worker,返回数据刷新ui
postToWorker(type: AdjustId, value: number, workerName: string) {let sliderValue = type === AdjustId.BRIGHTNESS ? this.brightnessLastSlider : this.saturationLastSlider;try {let workerInstance = new worker.ThreadWorker(workerName);const bufferArray = new ArrayBuffer(this.pixelMap.getPixelBytesNumber());this.pixelMap.readPixelsToBuffer(bufferArray).then(() => {let message = new MessageItem(bufferArray, sliderValue, value);workerInstance.postMessage(message);if (this.postState) {this.deviceListDialogController.open();}this.postState = false;workerInstance.onmessage = (event: MessageEvents) => {this.updatePixelMap(event)};if (type === AdjustId.BRIGHTNESS) {this.brightnessLastSlider = Math.round(value);} else {this.saturationLastSlider = Math.round(value);}workerInstance.onexit = () => {if (workerInstance !== undefined) {workerInstance.terminate();}}});} catch (error) {Logger.error(`Create work instance fail, error message: ${JSON.stringify(error)}`);}
}// AdjustSaturationWork.ts
// worker线程处理部分
workerPort.onmessage = function(event : MessageEvents) {let bufferArray = event.data.buf;let last = event.data.last;let cur = event.data.cur;let buffer = adjustSaturation(bufferArray, last, cur)workerPort.postMessage(buffer);workerPort.close();
}// AdjustUtil.ets
// 倍率计算部分
export function adjustSaturation(bufferArray: ArrayBuffer, last: number, cur: number) {return execColorInfo(bufferArray, last, cur, HSVIndex.SATURATION);
}

图片编码

图片位图经过处理之后,还是属于解码的状态,还需要进行打包编码成对应的格式,本章讲解编码的具体过程。

  1. 通过image组件创建打包工具packer。
  2. 使用PackingOption进行打包参数设定,比如格式、压缩质量等。
  3. 打包成图片信息数据imageData。
  4. 创建媒体库media,获取公共路径。
  5. 创建媒体文件asset,获取其fd。
  6. 使用fs将打包好的图片数据写入到媒体文件asset中。
// ImageSelect.ets
async encode(pixelMap: PixelMap | undefined) {if (pixelMap === undefined) {return;}const newPixelMap = pixelMap;// 打包图片const imagePackerApi = image.createImagePacker();const packOptions: image.PackingOption = {format: CommonConstants.ENCODE_FORMAT,quality: CommonConstants.ENCODE_QUALITY}const imageData = await imagePackerApi.packing(newPixelMap, packOptions);Logger.info(TAG, `imageData's length is ${imageData.byteLength}`);// 获取相册路径const context = getContext(this);const media = mediaLibrary.getMediaLibrary(context);const publicPath = await media.getPublicDirectory(mediaLibrary.DirectoryType.DIR_IMAGE);const currentTime = new Date().getTime();// 创建图片资源const imageAssetInfo = await media.createAsset(mediaLibrary.MediaType.IMAGE,`${CommonConstants.IMAGE_PREFIX}_${currentTime}${CommonConstants.IMAGE_FORMAT}`,publicPath);const imageFd = await imageAssetInfo.open(CommonConstants.ENCODE_FILE_PERMISSION);await fs.write(imageFd, imageData);// 释放资源await imageAssetInfo.close(imageFd);imagePackerApi.release();await media.release();
}

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

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

相关文章

【书生浦语第二期实战营学习笔记作业(四)】

课程文档&#xff1a;https://github.com/InternLM/Tutorial/blob/camp2/xtuner/readme.md 作业文档&#xff1a;https://github.com/InternLM/Tutorial/blob/camp2/xtuner/homework.md 书生浦语第二期实战营学习笔记&作业(四) 1.1、微调理论讲解及 XTuner 介绍 两种Fin…

不要摆摊,不要开早餐店,原因如下

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 我最近开通了视频号会员专区嘛&#xff0c;专区有个问答功能可以提问&#xff0c;有个会员问了我问题&#xff0c;其中一条问答分享给大家&#xff1a; 松哥&#xff0c;突然想去兼职&#xff0c;早上卖点杂粮煎饼果…

C语言自定义类型【结构体】

结构体的概念 结构是一些值的集合&#xff0c;这些值被称为成员变量。结构的每个成员可以是不同类型的变量。 1.结构体的声明 1.1普通声明 我们假设要创建一本书的类型&#xff0c;那我们需要书名&#xff0c;作者&#xff0c;价格&#xff0c;书的ID 代码如下&#xff1a;…

2024年04月09日 Go生态洞察:2024年上半年Go开发者调查报告洞察

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a;…

Linux——web基础实验

实验前的安装 [rootwebserver ~]# yum -y install httpd [rootwebserver ~]# systemctl enable --now httpd Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service. [rootwebserver ~]# echo test for apach…

性能监控数据(本地、服务器)

CPU、内存、磁盘等的监控 一、mac本地性能监控 1. top 终端&#xff1a; top load Avg: 平均负载(1分钟&#xff0c;5 分钟&#xff0c;15 分钟)值不能超过 4&#xff0c;要不然就是超负荷运行 Tasks: 进程数 %Cpu(s): idle :剩余百分比 KiB Mem: free:剩余内存&#xff0…

再谈C语言——理解指针(五)(完结篇)

数组名的理解 在上⼀个章节我们在使⽤指针访问数组的内容时&#xff0c;有这样的代码&#xff1a; int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址&#xff0c;但是其实数组名本来就是地址&#xf…

视频剪辑新高度:轻松为视频添加字幕,提升内容质量与传播力

视频已经成为最直观、最动人的信息传播方式。但是&#xff0c;仅仅依靠画面和声音&#xff0c;往往难以完全传达视频的核心内容或情感。这时&#xff0c;字幕的加入就显得尤为重要。它们不仅能够增强观众的观看体验&#xff0c;还能为视频增添独特的文字魅力。 首先&#xff0…

让你的电脑准时“打个盹”:Win10定时休眠

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 一、Windows 10任务计划程序 在快节奏的工作生活中&#xff0c;常常需要让电脑在特定时间执行某些任务&#xff0c;而Windows 10的任务计划程序就是为此而生的神器。它不仅可以自动更新系统、备份文件&#xff0c;甚…

九泰智库 | 医械周刊- Vol.23

⚖️ 法规动态 新疆药品和医疗器械产品注册费收费标准大幅降低平均降幅95% 近日&#xff0c;新疆自治区发展和改革委会同自治区财政厅印发《关于调整药品医疗器械产品注册费收费标准的通知》&#xff0c;明确自2024年4月29日起&#xff0c;取消药品补充申请注册费&#xff0c;药…

打造人脸磨皮算法新标杆,满足企业多元化需求

高清视频和图片已成为企业展示形象、传递信息的重要载体&#xff0c;拍摄过程中难以避免的皮肤瑕疵和纹理不均等问题&#xff0c;常常让精美的画面失色。美摄科技凭借其领先的人脸磨皮算法解决方案&#xff0c;为企业提供了高效、精细的图像处理服务&#xff0c;让每一帧画面都…

Git ignore、exclude for TortoiseGit 小结

1.Ignore Type&#xff1a;忽略类型&#xff0c;也即忽略规则&#xff0c;如何去忽略文件? 1.1.Ignore item(s) only in containing folder(s)&#xff1a;仅忽略在包含在文件夹中项目。 仅忽略该文件夹下选定的patterns。the patterns其实就是文件类型&#xff0c;比如.txt后…

python安装pytorch@FreeBSD

先上结论&#xff0c;最后在conda下安装成功了&#xff01; PyTorch是一个开源的人工智能深度学习框架&#xff0c;由Facebook人工智能研究院&#xff08;FAIR&#xff09;基于Torch库开发并维护。PyTorch提供了一个高效、灵活且易于使用的工具集&#xff0c;用于构建和训练深…

SpringMVC基础篇(一)

文章目录 1.基本介绍1.特点2.SpringMVC跟SpringBoot的关系 2.快速入门1.需求分析2.图解3.环境搭建1.创建普通java工程2.添加web框架支持3.配置lib文件夹1.导入jar包2.Add as Library3.以后自动添加 4.配置tomcat1.配置上下文路径2.配置热加载 5.src下创建Spring配置文件applica…

找不到openjdk-1.8-tools和openjdk-1.8-jconsole

每次打包都报找不到openjdk-1.8-tools和openjdk-1.8-jconsole&#xff0c;但是在项目中并没有用到。 这个是在maven仓库下的druid下的pom文件中。根本没有用到&#xff0c;于是把这两行注释调。解决 .m2\repository\com\alibaba\druid\1.2.6\druid-1.2.6.pom

钡铼IOy系列模块在无人值守智能仓库中的成功运用,提升仓储物流效率

随着科技的不断发展&#xff0c;无人值守智能仓库正成为现代物流行业的一个重要趋势。在这个快节奏的时代&#xff0c;提升仓储物流效率是企业追求的目标之一。钡铼IOy系列模块为无人值守智能仓库的成功运作提供了关键支持。本文将探讨钡铼IOy系列模块在无人值守智能仓库中的应…

深入Linux下的GCC编译器:从入门到精通

目录标题 1、GCC编译器概述2、安装GCC3、GCC的基本使用4、高级功能4.1 多文件编译4.2 静态和动态链接4.3 什么是链接&#xff1f;4.4 静态链接优点缺点 4.5 动态链接优点缺点 4.6 实际应用4.7 编译优化 GCC&#xff08;GNU Compiler Collection&#xff09;是一款免费、开源的编…

Elasticsearch下载

1 最新版下载地址 Download Elasticsearch | Elastic https://www.elastic.co/cn/downloads/elasticsearch 2 其他版本下载地址 https://www.elastic.co/cn/downloads/past-releases#elasticsearch 7.9.2:https://artifacts.elastic.co/downloads/elasticsearch/elasticsear…

基于springboot+vue+Mysql的篮球竞赛预约平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…