两张图片进行分析

2024-06-04 23:12
文章标签 分析 进行 图片 两张

本文主要是介绍两张图片进行分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

两张图片进行分析,可以拖动左边图片进行放大、缩小查看图片差异

 

底图

 

<template><div class="box_container"><section><div class="" v-for="item in imgData.imgDataVal" :key="item.id"><img :style="{width: boxStyle.width + '%',top: boxStyle.top,left: boxStyle.left,}" :src="item.src" :alt="item.name" /><div v-if="clickState" class="selectRegion":style="{ top: selectRegionStyle.top, left: selectRegionStyle.left }"></div><div class="text"><p>{{ item.name }}</p></div></div><div ref=" moveDom" id="moveDom"></div></section><p   class="p-diff">差别【不准确】: {{ differencePercentage }}%</p></div>
</template><script lang="ts" setup>import imageYT from '../assets/yt.png';
import imageFX from '../assets/fx.png';
import pixelmatch from 'pixelmatch';import { reactive, ref, onMounted, onBeforeUnmount } from 'vue';let differencePercentage = ref(0);
onMounted(() => {compareImages();
});
function compareImages() {const imgA = document.createElement('img');const imgB = document.createElement('img');imgA.onload = () => {imgB.onload = () => {const width = imgA.width;const height = imgA.height;const canvasA = document.createElement('canvas');const canvasB = document.createElement('canvas');canvasA.width = width;canvasA.height = height;canvasB.width = width;canvasB.height = height;const ctxA = canvasA.getContext('2d') as any;const ctxB = canvasB.getContext('2d') as any;ctxA.drawImage(imgA, 0, 0);ctxB.drawImage(imgB, 0, 0);const dataA = ctxA.getImageData(0, 0, width, height);const dataB = ctxB.getImageData(0, 0, width, height);const diff = pixelmatch(dataA.data, dataB.data, null, width, height);differencePercentage.value =100 - parseInt(((diff / (width * height)) * 100).toFixed(2));};imgB.src = imageFX as any;};imgA.src = imageYT as any;
}let imgData = reactive({imgDataVal: [{id: 1,name: '原始图',src: imageYT},{id: 2,name: '分析图',src: imageFX}]
})/*** @description: 添加鼠标事件* @return {*}*/const init = () => {moveDom.value = document.getElementById('moveDom')moveDom.value.addEventListener('mousemove', moveEvent)moveDom.value.addEventListener('wheel', wheelEvent)moveDom.value.addEventListener('mousedown', mousedownEvent)moveDom.value.addEventListener('mouseup', mouseupEvent)moveDom.value.addEventListener('mouseout', mouseoutEvent)moveDom.value.addEventListener('mouseover', mouseoverEvent)
}
onMounted(() => {init()
})const moveDom: any = ref(null);
const images: any = ref(null);
images.value = document.getElementsByClassName('chatImgs');
/*** @description: 卸载鼠标事件* @return {*}*/
onBeforeUnmount(() => {moveDom.value.removeEventListener('mousemove', moveEvent);moveDom.value.removeEventListener('mouseleave', wheelEvent);moveDom.value.removeEventListener('mousedown', mousedownEvent);
});
const boxStyle = ref({width: 50,top: '50%',left: '50%',
});
const selectRegionStyle = ref({top: '50%',left: '50%',
});
const moveX = ref(null);
const moveY = ref(null);/*** @description: 鼠标移动事件* @param {*} e* @return {*}*/
const moveEvent = (e: any) => {moveX.value = e.offsetX;moveY.value = e.offsetY;selectRegionStyle.value.left = `${e.offsetX}px`;selectRegionStyle.value.top = `${e.offsetY}px`;if (clickState.value) {boxStyle.value.top = `${e.offsetY}px`;boxStyle.value.left = `${e.offsetX}px`;}
};
/*** @description: 滚轮事件* @param {*} e* @return {*}*/
const wheelEvent = (e: any) => {if (e.deltaY < 0) {if (boxStyle.value.width > 200) {return;}boxStyle.value.width = boxStyle.value.width + 10;} else {if (boxStyle.value.width < 50) {return;}boxStyle.value.width = boxStyle.value.width - 10;}
};const clickState = ref(false);
const overState = ref(false);
/*** @description: 鼠标左键按下事件* @param {*} e* @return {*}*/
const mousedownEvent = (e: any) => {clickState.value = true;overState.value = true;
};
/*** @description: 鼠标移入事件* @param {*} e* @return {*}*/
const mouseoverEvent = (e: any) => {if (overState.value) {clickState.value = true;}
};
/*** @description: 鼠标左键抬起事件* @param {*} e* @return {*}*/
const mouseupEvent = (e: any) => {clickState.value = false;overState.value = false;
};
/*** @description: 鼠标移出事件* @param {*} e* @return {*}*/
const mouseoutEvent = (e: any) => {clickState.value = false;
};
</script><style scoped lang="scss">
.box_container {width: 100vw;height: 100vh;padding: 0;}section {width: 100%;height: 85%;display: flex;justify-content: center;justify-items: center;>div {flex: 1;height: 100%;position: relative;overflow: hidden;background-color: #0decb8da;box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.07);img {width: 100%;position: absolute;transform: translate(-50%, -50%);z-index: 0;}.selectRegion {position: absolute;width: 100px;height: 100px;transform: translate(-50%, -50%);border: 1px solid rgba(0, 0, 0, 0.3);}}// 左边区域可以拖动#moveDom {width: 49.8%;height: 85.0%;background-color: rgba(0, 0, 0, 0);position: absolute;top: 0;left: 0;cursor: move;}>div:nth-child(1) {margin-right: 5px;}>div:nth-child(2) {cursor: no-drop;margin-left: 5px;}.text {width: 100%;height: 50px;position: absolute;bottom: 0;left: 0;background-color: rgba(0, 0, 0, 0.1);p {width: 100%;height: 100%;line-height: 100%;text-align: center;line-height: 50px;// color: #333;color: #fff;font-weight: 600;letter-spacing: 10px;font-size: 18px;}}
}
.p-diff{display: flex;justify-content: center;margin-top: 20px;font-size: 20px;font-weight:600
}
</style>

这篇关于两张图片进行分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1031394

相关文章

如何使用Lombok进行spring 注入

《如何使用Lombok进行spring注入》本文介绍如何用Lombok简化Spring注入,推荐优先使用setter注入,通过注解自动生成getter/setter及构造器,减少冗余代码,提升开发效... Lombok为了开发环境简化代码,好处不用多说。spring 注入方式为2种,构造器注入和setter

MySQL进行数据库审计的详细步骤和示例代码

《MySQL进行数据库审计的详细步骤和示例代码》数据库审计通过触发器、内置功能及第三方工具记录和监控数据库活动,确保安全、完整与合规,Java代码实现自动化日志记录,整合分析系统提升监控效率,本文给大... 目录一、数据库审计的基本概念二、使用触发器进行数据库审计1. 创建审计表2. 创建触发器三、Java

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

linux解压缩 xxx.jar文件进行内部操作过程

《linux解压缩xxx.jar文件进行内部操作过程》:本文主要介绍linux解压缩xxx.jar文件进行内部操作,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、解压文件二、压缩文件总结一、解压文件1、把 xxx.jar 文件放在服务器上,并进入当前目录#

SpringBoot中如何使用Assert进行断言校验

《SpringBoot中如何使用Assert进行断言校验》Java提供了内置的assert机制,而Spring框架也提供了更强大的Assert工具类来帮助开发者进行参数校验和状态检查,下... 目录前言一、Java 原生assert简介1.1 使用方式1.2 示例代码1.3 优缺点分析二、Spring Fr

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期