有趣且重要的JS知识合集(19)前端实现图片的本地上传/截取/导出

input[file]太丑了,又不想去改button样式,那就自己实现一个上传按钮的div,然后点击此按钮时,去触发file上传的事件, 以下就是 原生js实现图片前端上传 并且按照最佳宽高比例展示图片,然后可以自定义截取图片,右侧预览区域 可以看到截图,最后还可以导出图片

1、效果图:

左侧为编辑区域,右侧为预览区域

2、文件目录 

3、实现源码: 

1、index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>image-cut</title><link rel="stylesheet" href="./assets/reset.css" /><link rel="stylesheet" href="./assets/main.css" /><link rel="stylesheet" href="./assets/rect.css" />
</head>
<!-- 图片裁剪 -->
<body><div id="root"><div id="tool" class="tool"><span id="insert-img" title="插入你想要截图的图片">插入图片</span><span id="start-paint" title="绘制矩形框并在右侧展示区生成canvas">开始截图</span><span id="clear" title="清除矩形框并清除右侧截图">清除截图</span><span id="export-clip" title="将右侧截图下载到本地">导出截图</span></div><div class="container"><div id="control" class="area"><div id="rect" class="rect"><span class="left-top dot"></span><span class="middle-top dot"></span><span class="right-top dot"></span><span class="right-middle dot"></span><span class="right-bottom dot"></span><span class="middle-bottom dot"></span><span class="left-bottom dot"></span><span class="left-middle dot"></span></div><div class="img-box"><img /></div></div><div id="display" class="area display"><canvas></canvas></div></div></div><!-- 矩形框脚本 --><script type="module" src="./srcipt/rect.js"></script><!-- 主控制区脚本 --><script type="module" src="./srcipt/main.js"></script>
</body>
</html>

2、/script/rect.js

import {methods
} from './main.js'const dom = document.querySelector('#control')
const rect  = document.querySelector('#rect')
const origin = dom.getBoundingClientRect()
const parentBorder = Number(getComputedStyle(dom, null).borderWidth.split('px')[0]) // 父元素边框 如果你明确知道边框宽度,就不需要这行,直接赋值就行
const childBorder = Number(getComputedStyle(rect, null).borderWidth.split('px')[0]) // 子元素边框 如果你明确知道边框宽度,就不需要这行,直接赋值就行
let finallPoint
/*** 开始绘制*/
const startMouse = () => {dom.style.cursor = 'crosshair'dom.onmousedown = e => {if (e.target !== dom) returnconst left = e.offsetXconst top = e.offsetYrect.style.left = left + 'px'rect.style.top = top + 'px'rect.style.borderColor = getCurrentColor() // 绘制时使用选择的框的颜色const childs = rect.childrenfor (let i = 0; i < childs.length; i++) {childs[i].style.borderColor = getCurrentColor() // 绘制时使用选择的框的颜色}dom.onmousemove = e => {// 宽高边界限制const widthArea = e.clientX - origin.x > dom.offsetWidth - (parentBorder * 2) ? dom.offsetWidth - (parentBorder * 2) : e.clientX - origin.xconst heightArea = e.clientY - origin.y > dom.offsetHeight - (parentBorder * 2) ? dom.offsetHeight - (parentBorder * 2) : e.clientY - origin.yrect.style.width = widthArea - left + 'px'rect.style.height = heightArea - top + 'px'}dom.onmouseup = e => {generatePoint()dom.onmousedown = nulldom.onmousemove = nulldom.onmouseup = nulldom.style.cursor = ''editMouse()}}
}
const editMouse = () => {rect.onmousedown = e => {if (e.target !== rect && e.target.className.indexOf('dot') === -1) return // 类名中包含被放行的dot除外const flag = mousedownHandle(e)let left = e.clientXlet top = e.clientYconst width = rect.offsetWidthconst height = rect.offsetHeightconst [dragX, dragY] = flag// 拖动if (dragX === -1 && dragY === -1) {left -= rect.offsetLeft // 要保持之前矩形框的坐标值top -= rect.offsetTop}const child = e.target.getBoundingClientRect()document.onmousemove = e => {// 取消浏览器因回流导致的默认事件及冒泡事件e.preventDefault()if (e.stopPropagation) {e.stopPropagation()} else {e.cancelable = true}finallPoint = {left: 0,top: 0,width: 0,height: 0}if (dragX === -1 && dragY === -1) {rect.style.cursor = 'move'const rightArea = dom.offsetWidth - rect.offsetWidth // 右边界const bottomArea = dom.offsetHeight - rect.offsetHeight // 下边界const leftArea = 0 // 左边界const topArea = 0 // 上边界finallPoint.left = e.clientX - left > rightArea ? rightArea : (e.clientX - left< leftArea ? leftArea : e.clientX - left)finallPoint.top = e.clientY - top > bottomArea ? bottomArea : (e.clientY - top < topArea ? topArea : e.clientY - top)rect.style.left = finallPoint.left + 'px'rect.style.top = finallPoint.top + 'px'} else if (dragX === 0 && dragY === 0) { // 左上角拉伸finallPoint.left = e.clientX > origin.x ? ((e.clientX > (left + width)) ? left + width - origin.x : e.clientX - origin.x) : 0finallPoint.top = e.clientY > origin.y ? ((e.clientY > (top + height)) ? top + height - origin.y : e.clientY - origin.y) : 0finallPoint.width = e.clientX > origin.x ? ((e.clientX > (left + width)) ? 0 : width + (left - e.clientX)) : width + (left - origin.x)finallPoint.height = e.clientY > origin.y ? ((e.clientY > (top + height)) ? 0 : height + (top - e.clientY)) : height + (top - origin.y)rect.style.left = finallPoint.left + 'px'rect.style.top = finallPoint.top + 'px'rect.style.width = finallPoint.width + 'px'rect.style.height = finallPoint.height + 'px'} else if (dragX === 1 && dragY === 0) { // 中上拉伸finallPoint.top = e.clientY > origin.y ? ((e.clientY > (top + height)) ? top + height - origin.y : e.clientY - origin.y) : 0finallPoint.height = e.clientY > origin.y ? ((e.clientY > (top + height)) ? 0 : height + (top - e.clientY)) : height + (top - origin.y)rect.style.top = finallPoint.top + 'px'rect.style.height = finallPoint.height + 'px'} else if (dragX === 2 && dragY === 0) { // 右上角拉伸finallPoint.top = e.clientY > origin.y ? ((e.clientY > (top + height)) ? top + height - origin.y : e.clientY - origin.y) : 0finallPoint.width = (e.clientX - left + width > dom.offsetWidth - rect.offsetLeft - (parentBorder * 2) ? dom.offsetWidth - rect.offsetLeft - (parentBorder * 2) : e.clientX - left + width)finallPoint.height = e.clientY > origin.y ? ((e.clientY > (top + height)) ? 0 : height + (top - e.clientY)) : height + (top - origin.y)rect.style.top = finallPoint.top + 'px'rect.style.width = finallPoint.width + 'px'rect.style.height = finallPoint.height + 'px'} else if (dragX === 2 && dragY === 1) { // 右中拉伸finallPoint.width = (e.clientX - left + width > dom.offsetWidth - rect.offsetLeft - (parentBorder * 2) ? dom.offsetWidth - rect.offsetLeft - (parentBorder * 2) : e.clientX - left + width)rect.style.width = finallPoint.width + 'px'}else if (dragX === 2 && dragY === 2) { // 右下角拉伸finallPoint.width = (e.clientX - left + width > dom.offsetWidth - rect.offsetLeft - (parentBorder * 2) ? dom.offsetWidth - rect.offsetLeft - (parentBorder * 2) : e.clientX - left + width)finallPoint.height = (e.clientY- top + height > dom.offsetHeight - rect.offsetTop - (parentBorder * 2) ? dom.offsetHeight - rect.offsetTop - (parentBorder * 2) : e.clientY- top + height)rect.style.width = finallPoint.width + 'px'rect.style.height = finallPoint.height + 'px'} else if (dragX === 1 && dragY === 2) { // 中下拉伸finallPoint.height = (e.clientY- top + height > dom.offsetHeight - rect.offsetTop - (parentBorder * 2) ? dom.offsetHeight - rect.offsetTop - (parentBorder * 2) : e.clientY- top + height)rect.style.height = finallPoint.height + 'px'} else if (dragX === 0 && dragY === 2) { // 左下角拉伸finallPoint.left = e.clientX > origin.x ? ((e.clientX > (left + width)) ? left + width - origin.x : e.clientX - origin.x) : 0finallPoint.width = e.clientX > origin.x ? ((e.clientX > (left + width)) ? 0 : width + (left - e.clientX)) : width + (left - origin.x)finallPoint.height = (e.clientY- top + height > dom.offsetHeight - rect.offsetTop - (parentBorder * 2) ? dom.offsetHeight - rect.offsetTop - (parentBorder * 2) : e.clientY- top + height)rect.style.left = finallPoint.left + 'px'rect.style.width = finallPoint.width + 'px'rect.style.height = finallPoint.height + 'px'} else if (dragX === 0 && dragY === 1) { // 左中拉伸finallPoint.left = e.clientX > origin.x ? ((e.clientX > (left + width)) ? left + width - origin.x : e.clientX - origin.x) : 0finallPoint.width = e.clientX > origin.x ? ((e.clientX > (left + width)) ? 0 : width + (left - e.clientX)) : width + (left - origin.x)rect.style.left = finallPoint.left + 'px'rect.style.width = finallPoint.width + 'px'}generatePoint()}document.onmouseup = e => {document.onmousemove = nulldocument.onmouseup = nullrect.style.cursor = 'move'}}
}
/*** mousedown逻辑处理*/
const mousedownHandle = (e) => {let flag = 0 // 点击的是除边角以外的其他部分 拖动let startX = e.offsetXlet startY = e.offsetYlet width = e.target.offsetWidthlet height = e.target.offsetHeightif (e.target !== rect) {flag = 1 // 点击的是边角 缩放const parent = e.target.offsetParent.getBoundingClientRect()const child = e.target.getBoundingClientRect()startX = child.x - parent.xstartY = child.y - parent.ywidth = e.target.offsetParent.offsetWidthheight = e.target.offsetParent.offsetHeight}const difference = 12 // 点击四边角12 px范围为拉伸,其他为拖动,这个值可以根据你需要的来调整let left = 0 // 0 => left, 1 => middle, 2 => right, -1 => 点击的位置不能被拖动let top = 0 // 0 => top, 1 => middle, 2 => bottom, -1 => 点击的位置不能被拖动if (startX < difference) { // 点击的位置为矩形左侧left = 0} else if (startX > width / 2 - difference && startX < width / 2 + difference) { // 点击的位置为矩形中间 width/2 - 6px ~ width/2 + 6pxleft = 1} else if (startX < width && startX > width - difference){ // 点击的位置为矩形右侧 width - 6px ~ widthleft = 2} else {left = -1}if (startY < difference) { // 点击的位置为矩形上侧top = 0} else if (startY > height / 2 - difference && startY < height / 2 + difference) { // 点击的位置为矩形中间 height/2 - 6px ~ height/2 + 6pxtop = 1} else if (startY < height && startY > height - difference){ // 点击的位置为矩形下侧 height - 6px ~ heighttop = 2} else {top = -1}if (left === -1 || top === -1 || (left === 1 && top === 1)) {return [-1, -1]}return [left, top] // 只会有八个位置能被准确返回,其余都是返回[-1, -1]
}const clear = document.querySelector('#clear') // 清除截图
const startPaint = document.querySelector('#start-paint') // 开始绘制const getCurrentColor = () => {return '#fa9120'
}
/** 生成最终坐标 */
const generatePoint = () => {const rectArgs = {left: parseInt(getComputedStyle(rect).left),top: parseInt(getComputedStyle(rect).top),width: parseInt(getComputedStyle(rect).width),height: parseInt(getComputedStyle(rect).height),}methods.generateImg(rectArgs)
}
/** 清除矩形框 */
export const clearRect = () => {rect.style.left = '-9999px'rect.style.top = 0rect.style.width = 0rect.style.height = 0
}clear.onclick = e => {methods.clearCanvas()clearRect()
}
startPaint.onclick = e => {startMouse()
}

3、/script/main.js

import {clearRect
} from './rect.js';// 编辑区dom
const control = document.querySelector('#control')
// 编辑区显示的图片dom
const controlImg = document.querySelector('#control img')
// 预览区dom
const display = document.querySelector('#display')
// 预览区显示的canvas dom
const canvas = document.querySelector('#display canvas')
const ctx = canvas.getContext('2d')
// 插入图片的dom
const insertImg = document.querySelector('#insert-img')
// 导出截图的dom
const exportClip = document.querySelector('#export-clip')
// 图片对象
let imgObj = null
// 最佳显示比例
let bestScale = 0
const methods = {/** ------ 图片上传模块 开始 ------ */doInput() {const inputObj = document.createElement('input');inputObj.addEventListener('change', this.readFile, false);inputObj.type = 'file';inputObj.accept = 'image/*';inputObj.click();},readFile() {const file = this.files[0]; // 获取input输入的图片if(!/image\/\w+/.test(file.type)){alert("请确保文件为图像类型");return false;} // 判断是否图片const reader = new FileReader();reader.readAsDataURL(file); // 转化成base64数据类型reader.onload = function(e){methods.drawToCanvas(this.result); // lve为当前实例}},drawToCanvas(imgData) {imgObj = new Image()controlImg.src = imgObj.src = imgDataimgObj.onload = () => {bestScale = methods.calcBestScale(imgObj, control.offsetWidth, control.offsetHeight)// 图片按最佳比例展示controlImg.width = imgObj.width * bestScalecontrolImg.height = imgObj.height * bestScale// 外部盒子也按照最佳比例展示control.style.width = controlImg.width + 'px'control.style.height = controlImg.height + 'px'}},/** ------ 图片上传模块 结束 ------ *//*** 随机id*/uuid() {let d = new Date().getTime();const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {const r = (d + Math.random() * 16) % 16 | 0;d = Math.floor(d / 16);return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);});return uuid},/*** canvas转base64* @param {*} blob* @param {*} type* @param {*} name*/blob2file(blob, type = 'png', name = '') {const fileName = name || this.uuid() + '.' + typeconst file = new File([blob], fileName, { type: blob.type, lastModified: Date.now() })return file},/*** 计算最佳的图片显示比例* @param {*} img* @param {*} deviceWidth* @param {*} deviceHeight* @returns */calcBestScale(img, deviceWidth, deviceHeight) {return Math.min(deviceWidth / img.width, deviceHeight / img.height)},/*** 清除canvas*/clearCanvas() {canvas && ctx.clearRect(0, 0, display.offsetWidth, display.offsetHeight)},/*** 生成图片* @param {*} src */generateImg(rect) {if (!imgObj) returnconst {left,top,width,height} = rectconst displayRect = {left: left / bestScale,top: top / bestScale,width: width / bestScale,height: height / bestScale}// 当截图矩形框宽度大于高度时,以预览区宽度为限制,高度按比例缩放if (displayRect.width >  displayRect.height) {canvas.width = display.offsetWidthcanvas.height = display.offsetWidth * displayRect.height / displayRect.width// 当截图矩形框高度大于宽度时,以预览区高度为限制,宽度按比例缩放} else {canvas.height = display.offsetHeightcanvas.width = display.offsetHeight * displayRect.width / displayRect.height}ctx.drawImage(imgObj, displayRect.left, displayRect.top, displayRect.width, displayRect.height, 0, 0, canvas.width, canvas.height)}
}
/** 点击插入图片触发逻辑 */
insertImg.addEventListener('click', () => {clearRect()methods.doInput()
})/** 点击导出截图触发逻辑 */
exportClip.addEventListener('click', () => {if (canvas) {// 创建一个 a 标签,并设置 href 和 download 属性const el = document.createElement('a');// 设置 href 为图片经过 base64 编码后的字符串,默认为 png 格式el.href = canvas.toDataURL('image/png', 1.0);el.download = '截图.png';// 创建一个点击事件并对 a 标签进行触发const event = new MouseEvent('click');el.dispatchEvent(event);}
})export {methods
}

4、/assets/rect.css

.rect{position: absolute;/* box-shadow: 0 0 0 1999px rgba(0, 0, 0, .4); */left: -9999px;top: 0;width: 0;height: 0;border: 1px solid #d79751;cursor: move;z-index: 1;
}
.rect > span{position: absolute;width: 4px;height: 4px;/* border-radius: 50%; */border: 1px solid #fa9120;background-color: #fa9120;
}
.rect .left-top{left: -3px;top: -3px;cursor: nwse-resize;
}
.rect .middle-top{left: 50%;top: -3px;transform: translateX(-50%);cursor: n-resize;
}
.rect .right-top{right: -3px;top: -3px;cursor: nesw-resize;
}
.rect .right-middle{right: -3px;top: 50%;transform: translateY(-50%);cursor: e-resize;
}
.rect .right-bottom{right: -3px;bottom: -3px;cursor: nwse-resize;
}
.rect .middle-bottom{left: 50%;bottom: -3px;transform: translateX(-50%);cursor: s-resize;
}
.rect .left-bottom{left: -3px;bottom: -3px;cursor: nesw-resize;
}
.rect .left-middle{left: -3px;top: 50%;transform: translateY(-50%);cursor: w-resize;
}

5、/assets/main.css

body {position: relative;width: 100vw;height: 100vh;
}#root {width: 80%;height: 624px;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);
}.tool {padding: 0 10px;line-height: 24px;height: 24px;width: 100%;
}.tool span {cursor: pointer;
}.tool span:hover {color: #fa9120;
}.container {width: 100%;height: calc(100% - 24px);position: relative;display: flex;
}.area {width: 50%;max-width: 50%;height: 100%;border: 2px dashed #eee;border-radius: 8px;position: relative;
}.area .img-box {position: absolute;left: 0;height: 0;z-index: -1;pointer-events: none;
}.area img {pointer-events: none;
}#control canvas {width: 100%;height: 100%;position: absolute;left: 0;top: 0;z-index: -1;
}

6、/assets/reset.css(初始化样式表,这个可以你自行实现)

* {box-sizing: border-box;
}body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
pre,
form,
fieldset,
legend,
button,
input,
textarea,
th,
td {margin: 0;padding: 0;
}body,
button,
input,
select,
textarea {font: 12px/1.5tahoma, arial, \5b8b\4f53;
}h1,
h2,
h3,
h4,
h5,
h6 {font-size: 100%;
}address,
cite,
dfn,
em,
var {font-style: normal;
}code,
kbd,
pre,
samp {font-family: couriernew, courier, monospace;
}small {font-size: 12px;
}ul,
ol {list-style: none;
}a {text-decoration: none;
}a:hover {text-decoration: none;
}legend {color: #000;
}fieldset,
img {border: 0;
}button,
input,
select,
textarea {font-size: 100%;
}table {border-collapse: collapse;border-spacing: 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

全面解析企业财务报表系列之二:财务状况等式

全面解析企业财务报表系列之二&#xff1a;财务状况等式 一、财务状况等式二、会计恒等式三、复试记账法四、经营成果等式五、第三会计等式 一、财务状况等式 会计恒等式复试记账法权责发生制 二、会计恒等式 资产负债所有者权益 三、复试记账法 每笔交易至少在两个账户中记…

Kafka:kafka的技术架构? ①

一、Kafka的优势 Apache Kafka是一个开放源代码的分布式事件流平台&#xff0c;成千上万的公司使用它来实现高性 能数据管道&#xff0c;流分析&#xff0c;数据集成和关键任务等相关的应用程序。 二、技术架构 0&#xff09;partition分区可以设置备份数&#xff0c;也可以设…

关于电脑功耗与电费消耗的问题,你了解多少?

一台电脑24小时运行需要多少电量&#xff1f; 大家好&#xff0c;我是一名拥有多年维修经验的上门维修师傅。 今天我就来回答大家关于电脑24小时运行需要多少电量的问题。 电脑功耗及用电量 首先我们来看看电脑的功耗情况。 普通台式电脑的功耗通常在300瓦左右&#xff0c;即…

Jenkins使用遇到的一些问题

一&#xff1a;插件依赖报错 比如遇到一堆插件报错&#xff0c;不是提示版本对不上&#xff0c;就是启用不了 这样直接把Jenkins升级就行了&#xff0c;比如我这个是命令行启动的&#xff0c;直接把他替换就好了 如果是遇到插件依赖报错&#xff0c;比如A插件异常 则点击这个插…

Python爬虫技术详解:从基础到高级应用,实战与应对反爬虫策略【第93篇—Python爬虫】

前言 随着互联网的快速发展&#xff0c;网络上的信息爆炸式增长&#xff0c;而爬虫技术成为了获取和处理大量数据的重要手段之一。在Python中&#xff0c;requests模块是一个强大而灵活的工具&#xff0c;用于发送HTTP请求&#xff0c;获取网页内容。本文将介绍requests模块的…

力扣hot100题解(python版7-9题)

7、接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,…

JSON(javaScript Object Notation,Js对象标记)—我耀学IT

Json是一种轻量级的数据交换格式&#xff0c;目前使用非常广泛&#xff0c;是一种轻量级的数据交换格式。易于人阅读和编写&#xff0c;可以在多种语言之间进行数据交换 。同时也易于机器解析和生成 1.1json的值: 值可以是对象、数组、数字、字符串或者三个字面值(false、nul…

PBM模型学习

本专栏着重讲解PBM学习所得&#xff0c;学习笔记、心得&#xff0c;并附有视频素材资料&#xff0c;视频详细目录如下&#xff1a; PBM相关参数解释1 PBM相关参数解释2 PBM相关案例实践1 PBM相关案例实践2 PBM相关案例实践2 PBM相关案例实践3 PBM多相流中次相界面设置1 PBM多相…

Ubuntu20.04开启/禁用ipv6

文章目录 Ubuntu20.04开启/禁用ipv61.ipv62. 开启ipv6step1. 编辑sysctl.confstep2. 编辑网络接口配置文件 3. 禁用ipv6&#xff08;sysctl&#xff09;4. 禁用ipv6&#xff08;grub&#xff09;附&#xff1a;总结linux网络配置 Ubuntu20.04开启/禁用ipv6 1.ipv6 IP 是互联网…

mysql和sql server 中如何创建和管理用户

阅读本文之前请参阅----MySQL 数据库安装教程详解&#xff08;linux系统和windows系统&#xff09; 在MySQL和SQL Server中创建和管理用户的过程有所不同。下面分别介绍这两种数据库系统中用户管理的常见步骤。 MySQL 创建用户 在MySQL中创建用户的语法通常如下…

Oracle迁移到mysql-表结构的坑

1.mysql中id自增字段必须是整数类型 id BIGINT AUTO_INCREMENT not null, 2.VARCHAR2改为VARCHAR 3.NUMBER(16)改为decimal(16,0) 4.date改为datetime 5.mysql范围分区必须int格式&#xff0c;不能list类型 ERROR 1697 (HY000): VALUES value for partition …

Redis 事务机制之ACID属性

事务属性 事务是对数据库进行读写的一系列操作。在事务执行时提供ACID属性保证&#xff1a; 包括原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;和持久性&#xff08;Durability&#xff09;…

YOLOv5改进 | Conv篇 | 利用YOLOv9的GELAN模块替换C3结构(附轻量化版本 + 高效涨点版本 + 结构图)

一、本文介绍 本文给大家带来的改进机制是利用2024/02/21号最新发布的YOLOv9其中提出的GELAN模块来改进YOLOv5中的C3,GELAN融合了CSPNet和ELAN机制同时其中利用到了RepConv在获取更多有效特征的同时在推理时专用单分支结构从而不影响推理速度,同时本文的内容提供了两种版本一…

8.qt5使用opencv的库函数打开图片

1.配置opencv动态库的环境变量 2.在创建的qt工程中加入如下opencv代码&#xff0c;具体代码如下&#xff1a; 使用opencv库函数显示图片

ACL权限、特殊位与隐藏属性的奥秘

1.2 操作步骤 # 1. 添加测试目录&#xff0c;用户&#xff0c;组&#xff0c;并将用户添加到组 ------------------- [rootlocalhost ~]# mkdir /project[rootlocalhost ~]# useradd zs[rootlocalhost ~]# useradd ls[rootlocalhost ~]# groupadd tgroup[rootlocalhost ~]# g…

亿道丨三防平板丨加固平板丨为零售业提供四大优势

随着全球经济的快速发展&#xff0c;作为传统行业的零售业也迎来了绝佳的发展机遇&#xff0c;在互联网智能化的大环境下&#xff0c;越来越多的零售企业选择三防平板电脑作为工作中的电子设备。作为一种耐用的移动选项&#xff0c;三防平板带来的不仅仅是坚固的外壳。坚固耐用…

4 buuctf解题

[CISCN 2019 初赛]Love Math1 打开题目 题目源码 <?php error_reporting(0); //听说你很喜欢数学&#xff0c;不知道你是否爱它胜过爱flag if(!isset($_GET[c])){show_source(__FILE__); }else{//例子 c20-1$content $_GET[c];if (strlen($content) > 80) {die("…

在项目中应用设计模式的实践指南

目录 ✨✨ 祝屏幕前的您天天开心&#xff0c;每天都有好运相伴。我们一起加油&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 引言 一. 单例模式&#xff08;Singleton Pattern&#xff09; 1、实现单例模式的方式 1…

回归预测 | Matlab实现PSO-BiLSTM-Attention粒子群算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测

回归预测 | Matlab实现PSO-BiLSTM-Attention粒子群算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测 目录 回归预测 | Matlab实现PSO-BiLSTM-Attention粒子群算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测预测效果基本描述程序设计参考资料 预测效果…

使用 yarn 的时候,遇到 Error [ERR_REQUIRE_ESM]: require() of ES Module 怎么解决?

晚上回到家&#xff0c;我打开自己的项目&#xff0c;执行&#xff1a; cd HexoPress git pull --rebase yarn install yarn dev拉取在公司 push 的代码&#xff0c;然后更新依赖&#xff0c;最后开始今晚的开发时候&#xff0c;意外发生了&#xff0c;竟然报错了&#xff0c;…