比较两张 canvas 图片(参考图片和网站上的当前图片)
Compare two canvas image (reference one and current on the website)
我想比较两张图片。我写了一段代码,结果显示图像是一样的,虽然实际上图像被改变了。我想要实现的是,当我按 'o' 键时,我想每 5 秒刷新一次网站,并将现在网站上的图像与我设置间隔时页面上的图像进行比较(通过按'o' 键)。图像具有相同的大小。
// @name Nowy123
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match http://*/*
// @grant none
// @include *.*
// ==/UserScript==
(function() {
'use strict';
// Your code here...
let intervalNum = localStorage.getItem('intervalNum');
console.log(intervalNum);
if(intervalNum){
clearInterval(intervalNum);
intervalNum = setInterval(specHero, 5000);
}
document.addEventListener("keydown", event => {
if (event.keyCode === 79) {
console.log("pressed o");
console.log("interval started");
//image
let img = document.querySelector('.contentContainer').querySelector('.heroImage');
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0 );
var refImg = context.getImageData(0, 0, img.width, img.height);
localStorage.setItem('refImg',refImg);
console.log(img);
intervalNum = setInterval(specHero, 5000);
localStorage.setItem('intervalNum', intervalNum);
}
});
document.addEventListener("keydown", event => {
if (event.keyCode === 80) {
console.log("pressed p");
console.log("interval stopped");
intervalNum = localStorage.getItem('intervalNum');
clearInterval(intervalNum);
window.localStorage.clear();
}
});
function specHero(){
let img = document.querySelector('.contentContainer').querySelector('.heroImage');
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0 );
var imgData = context.getImageData(0, 0, img.width, img.height);
let refImg = localStorage.getItem('refImg');
let result = isMatch(imgData, refImg);
console.log(result);
if(!result){
console.log("Found difference");
clearInterval(intervalNum);
return;
}
location.reload();
}
function isMatch(data1,data2){
for(var i = 0; i<data1.length; i++){
if(data1[i] != data2[i]) return false;
}
return true;
}
})();```
您可能想检查 localStorage
中实际存储的内容。剧透警告:这是字符串 "[object ImageData]"
.
localStorage.setItem('refImg',refImg)
不存储实际图像数据,它存储字符串 "[object ImageData]"
。这是因为 localStorage
只能存储字符串,当您尝试存储 non-string 值时,该值将通过调用 toString
转换为字符串。 toString
图像数据对象 return 字符串 "[object ImageData]"
.
由于您正在处理图像数据对象(通常是非常大的对象)并且您希望不断比较它们,因此使用 localStorage
(使用硬盘驱动器存储数据)可能会导致性能下降,此外,无论如何都没有一种直接的方法可以将图像数据存储在 localStorage
中。我建议您通过使用(半)全局变量来保存参考图像数据对象来将对象存储在内存中,如下所示:
(function() {
'use strict';
let refImageData; // this will hold the reference image data object instead of saving it to localStorage
document.addEventListener("keydown", event => {
/* ... */
refImageData = refImg; // instead of localStorage.setItem('refImg',refImg)
/* ... */
}
function specHero() {
/* ... */
let refImg = refImageData; // instead of let refImg = localStorage.getItem('refImg'), this is redundant anyway because refImageData is already accessible from the other functions
/* ... */
}
注意: 正如@Kaiido 在下面的评论中指出的那样,图像数据对象没有 length
属性,它们有 data
属性 保存实际的像素数据,所以 isMatch
应该是这样的:
function isMatch(data1, data2) {
for(let i = 0; i < data1.data.length; i++) {
if(data1.data[i] != data2.data[i]) {
return false;
}
}
return true;
}
编辑 - 将图像数据对象保存到 localStorage:
如果一定要将图片数据对象保存到本地,需要将图片数据对象(Uint8ClampedArray
类型)的data
属性转换成常规数组首先使用 Array.from
,然后 JSON.stringify
/JSON.parse
将该数组转换为字符串并返回数组。为此,我们使用了这两个辅助函数,一个用于保存,一个用于检索图像数据对象的 data
属性:
function saveImageData(key, imageData) {
localStorage.setItem(key, JSON.stringify(Array.from(imageData.data)));
}
function loadImageData(key) {
// it's probably a good idea to check if local storage has something saved before executing the following line of code
return JSON.parse(localStorage.getItem(key));
}
并将它们用于 save/retrieve,如下所示:
saveImageData("refImg", refImg); // instead of localStorage.setItem('refImg',refImg)
let refImg = loadImageData("refImg"); // instead of let refImg = localStorage.getItem('refImg');
请注意,这将仅保存图像数据对象的 data
数组,而不是图像数据对象本身。所以 isMatch
应该变成:
function isMatch(data1, data2) {
for(let i = 0; i < data1.length; i++) {
if(data1[i] != data2[i]) {
return false;
}
}
return true;
}
当您调用 isMatch
时,您只需传递图像数据对象的 data
数组,如下所示:
isMatch(imgData.data, refImg);
// imgData is an actual image data object so we need to access its 'data' property
// refImg is the 'data' array saved to local storage, no need to access 'data' on it
我想比较两张图片。我写了一段代码,结果显示图像是一样的,虽然实际上图像被改变了。我想要实现的是,当我按 'o' 键时,我想每 5 秒刷新一次网站,并将现在网站上的图像与我设置间隔时页面上的图像进行比较(通过按'o' 键)。图像具有相同的大小。
// @name Nowy123
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match http://*/*
// @grant none
// @include *.*
// ==/UserScript==
(function() {
'use strict';
// Your code here...
let intervalNum = localStorage.getItem('intervalNum');
console.log(intervalNum);
if(intervalNum){
clearInterval(intervalNum);
intervalNum = setInterval(specHero, 5000);
}
document.addEventListener("keydown", event => {
if (event.keyCode === 79) {
console.log("pressed o");
console.log("interval started");
//image
let img = document.querySelector('.contentContainer').querySelector('.heroImage');
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0 );
var refImg = context.getImageData(0, 0, img.width, img.height);
localStorage.setItem('refImg',refImg);
console.log(img);
intervalNum = setInterval(specHero, 5000);
localStorage.setItem('intervalNum', intervalNum);
}
});
document.addEventListener("keydown", event => {
if (event.keyCode === 80) {
console.log("pressed p");
console.log("interval stopped");
intervalNum = localStorage.getItem('intervalNum');
clearInterval(intervalNum);
window.localStorage.clear();
}
});
function specHero(){
let img = document.querySelector('.contentContainer').querySelector('.heroImage');
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0 );
var imgData = context.getImageData(0, 0, img.width, img.height);
let refImg = localStorage.getItem('refImg');
let result = isMatch(imgData, refImg);
console.log(result);
if(!result){
console.log("Found difference");
clearInterval(intervalNum);
return;
}
location.reload();
}
function isMatch(data1,data2){
for(var i = 0; i<data1.length; i++){
if(data1[i] != data2[i]) return false;
}
return true;
}
})();```
您可能想检查 localStorage
中实际存储的内容。剧透警告:这是字符串 "[object ImageData]"
.
localStorage.setItem('refImg',refImg)
不存储实际图像数据,它存储字符串 "[object ImageData]"
。这是因为 localStorage
只能存储字符串,当您尝试存储 non-string 值时,该值将通过调用 toString
转换为字符串。 toString
图像数据对象 return 字符串 "[object ImageData]"
.
由于您正在处理图像数据对象(通常是非常大的对象)并且您希望不断比较它们,因此使用 localStorage
(使用硬盘驱动器存储数据)可能会导致性能下降,此外,无论如何都没有一种直接的方法可以将图像数据存储在 localStorage
中。我建议您通过使用(半)全局变量来保存参考图像数据对象来将对象存储在内存中,如下所示:
(function() {
'use strict';
let refImageData; // this will hold the reference image data object instead of saving it to localStorage
document.addEventListener("keydown", event => {
/* ... */
refImageData = refImg; // instead of localStorage.setItem('refImg',refImg)
/* ... */
}
function specHero() {
/* ... */
let refImg = refImageData; // instead of let refImg = localStorage.getItem('refImg'), this is redundant anyway because refImageData is already accessible from the other functions
/* ... */
}
注意: 正如@Kaiido 在下面的评论中指出的那样,图像数据对象没有 length
属性,它们有 data
属性 保存实际的像素数据,所以 isMatch
应该是这样的:
function isMatch(data1, data2) {
for(let i = 0; i < data1.data.length; i++) {
if(data1.data[i] != data2.data[i]) {
return false;
}
}
return true;
}
编辑 - 将图像数据对象保存到 localStorage:
如果一定要将图片数据对象保存到本地,需要将图片数据对象(Uint8ClampedArray
类型)的data
属性转换成常规数组首先使用 Array.from
,然后 JSON.stringify
/JSON.parse
将该数组转换为字符串并返回数组。为此,我们使用了这两个辅助函数,一个用于保存,一个用于检索图像数据对象的 data
属性:
function saveImageData(key, imageData) {
localStorage.setItem(key, JSON.stringify(Array.from(imageData.data)));
}
function loadImageData(key) {
// it's probably a good idea to check if local storage has something saved before executing the following line of code
return JSON.parse(localStorage.getItem(key));
}
并将它们用于 save/retrieve,如下所示:
saveImageData("refImg", refImg); // instead of localStorage.setItem('refImg',refImg)
let refImg = loadImageData("refImg"); // instead of let refImg = localStorage.getItem('refImg');
请注意,这将仅保存图像数据对象的 data
数组,而不是图像数据对象本身。所以 isMatch
应该变成:
function isMatch(data1, data2) {
for(let i = 0; i < data1.length; i++) {
if(data1[i] != data2[i]) {
return false;
}
}
return true;
}
当您调用 isMatch
时,您只需传递图像数据对象的 data
数组,如下所示:
isMatch(imgData.data, refImg);
// imgData is an actual image data object so we need to access its 'data' property
// refImg is the 'data' array saved to local storage, no need to access 'data' on it