gpt4 book ai didi

javascript - 查找图像中的十六进制颜色和 X,Y

转载 作者:行者123 更新时间:2023-11-30 23:59:03 25 4
gpt4 key购买 nike

我正在尝试查找图像中的所有十六进制颜色,如果可能,圈出或突出显示十六进制颜色所在的 X、Y 位置。我当前的代码正在尝试查找所有颜色,几乎使我的浏览器崩溃,并且我尝试查找每个图像的 X、Y 坐标也进展不顺利。

我有两个函数做不同的事情,这就是我试图用它来给出一个已经尝试过的例子......任何帮助都会很棒!

任何帮助都会很棒!

<canvas id="myCanvas" width="240" height="297" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<img id="origImage" width="220" height="277" src="loggraph.PNG">
<script>
function getPixel(imgData, index) {
var i = index*4, d = imgData.data;
return [d[i],d[i+1],d[i+2],d[i+3]] // [R,G,B,A]
}

function getPixelXY(imgData, x, y) {
return getPixel(imgData, y*imgData.width+x);
}

function goCheck() {
var cvs = document.createElement('canvas'),
img = document.getElementsByTagName("img")[0];
cvs.width = img.width; cvs.height = img.height;
var ctx = cvs.getContext("2d");
ctx.drawImage(img,0,0,cvs.width,cvs.height);
var idt = ctx.getImageData(0,0,cvs.width,cvs.height);

console.log(getPixel(idt, 852)); // returns array [red, green, blue, alpha]
console.log(getPixelXY(idt,1,1)); // same pixel using x,y
}

function getColors(){
var canvas = document.getElementById("myCanvas");
var devices = canvas.getContext("2d");
var imageData = devices.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;


// iterate over all pixels
for(var i = 0, n = data.length; i < n; i += 4) {
var r = data[i];
var g = data[i + 1];
var b = data[i + 2];
var rgb = "("+r+","+g+","+b+")";

var incoming = i*4, d = imageData.data;
var bah = [d[incoming],d[incoming+1],d[incoming+2],d[incoming+3]];
$('#list').append("<li>"+rgb+"</li>");
colorList.push(rgb);
}
$('#list').append("<li>"+[d[incoming],d[incoming+1],d[incoming+2],d[incoming+3]]+"</li>");
}

}

最佳答案

必须检查所有像素

要找到与颜色匹配的像素,在最坏的情况下(该颜色的像素不在图像中),您需要遍历图像中的每个像素。

如何不这样做

将每个像素转换为 DOM 字符串是最糟糕的方法,因为 DOM 字符串使用大量内存和 CPU 开销,尤其是使用 jQuery 实例化时(它有自己的额外包袱)

十六进制颜色到数组

要查找像素,您只需对照十六进制值检查每个像素的颜色数据。您将十六进制值转换为 3 字节的数组。

以下函数将从 CSS Hex 格式转换 "#HHH" "#HHHH" , "#HHHHHH""#HHHHHHHH"忽略 alpha 部分(如果包含),将其转换为 0-255 的整数数组

const hex2RGB = h => {
if(h.length === 4 || h.length === 5) {
return [parseInt(h[1] + h[1], 16), parseInt(h[2] + h[2], 16), parseInt(h[3] + h[3], 16)];
}
return [parseInt(h[1] + h[2], 16), parseInt(h[3] + h[4], 16), parseInt(h[5] + h[6], 16)];
}

查找像素

我不知道您打算如何使用这样的功能,因此下面的示例是一个通用方法,将有所帮助,并且可以根据需要进行修改

如果你允许的话,即使没有完美的匹配,它总是会找到一个像素。它通过查找与您要查找的颜色最接近的颜色来实现此目的。

找到最接近匹配的原因是,当您将图像绘制到 2D Canvas 上时,如果图像具有透明像素(预乘 Alpha),则像素值会稍微修改

该函数通过测量像素和十六进制颜色之间的空间距离来查找像素(简单几何毕达哥拉斯)。最接近的颜色是距离最小的颜色。

它将返回对象

{
x, // the x coordinate of the match
y, // the y coordinate of the match
distance, // how closely the color matches the requested color.
// 0 means a perfect match
// to 441 completely different eg black and white
// value is floored to an integer value
}

如果图像被污染(跨源、本地设备存储),或者您传递了无法转换为像素的内容,则该函数将返回 undefined

该函数保留一个用于获取像素数据的 Canvas ,因为它假设它将被多次使用。如果图像被污染,它将捕获错误(向控制台添加警告),清理被污染的 Canvas 并为另一个图像做好准备。

用法

要使用该功能,请将其添加到您的代码库中,它将自动设置。

获取图像和十六进制值并使用 image 调用该函数, CSS hex颜色,以及颜色匹配的阈值距离(可选)。

例如查找 #FF0000 的完全匹配

const result = findPixel(origImage, "#FF0000", 0); // find exact match for red
if (result) { // only if found
console.log("Found color #FF0000 at pixel " + result.x + ", " + result.y);
} else {
console.log("The color #FF0000 is not in the image");
}

或找到接近的颜色

const result = findPixel(origImage, "#FF0000", 20); // find a match for red
// within 20 units.
// A unit is 1 of 256
if (result) { // only if found
console.log("Found closest color within " + result.distance + "units of #FF0000 at pixel " + result.x + ", " + result.y);
}

或找到最近的

// find the closest, no threshold ensures a result
const result = findPixel(origImage, "#FF0000");
console.log("Found closest color within " + result.distance + "units of #FF0000 at pixel " + result.x + ", " + result.y);

代码

函数如下。

const findPixel = (() => {
var can, ctx;
function createCanvas(w, h) {
if (can === undefined){
can = document.createElement("canvas");
ctx = can.getContext("2d");
}
can.width = w;
can.height = h;
}
function getPixels(img) {
const w = img.naturalWidth || img.width, h = img.naturalHeight || img.height;
createCanvas(w, h);
ctx.drawImage(img, 0, 0);
try {
const imgData = ctx.getImageData(0, 0, w, h);
can.width = can.height = 1; // make canvas as small as possible so it wont
// hold memory. Leave in place to avoid instantiation overheads
return imgData;
} catch(e) {
console.warn("Image is un-trusted and pixel access is blocked");
ctx = can = undefined; // canvas and context can no longer be used so dump them
}
return {width: 0, height: 0, data: []}; // return empty pixel data
}
const hex2RGB = h => { // Hex color to array of 3 values
if(h.length === 4 || h.length === 5) {
return [parseInt(h[1] + h[1], 16), parseInt(h[2] + h[2], 16), parseInt(h[3] + h[3], 16)];
}
return [parseInt(h[1] + h[2], 16), parseInt(h[3] + h[4], 16), parseInt(h[5] + h[6], 16)];
}
const idx2Coord = (idx, w) => ({x: idx % w, y: idx / w | 0});
return function (img, hex, minDist = Infinity) {
const [r, g, b] = hex2RGB(hex);
const {width, height, data} = getPixels(img);
var idx = 0, found;
while (idx < data.length) {
const R = data[idx] - r;
const G = data[idx + 1] - g;
const B = data[idx + 2] - b;
const d = R * R + G * G + B * B;
if (d === 0) { // found exact match
return {...idx2Coord(idx / 4, width), distance: 0};
}
if (d < minDist) {
minDist = d;
found = idx;
}
idx += 4;
}
return found ? {...idx2Coord(found / 4, width), distance: minDist ** 0.5 | 0 } : undefined;
}
})();

此功能已经过测试,并且按上述方式工作。

注意按照问题中的代码,图像的 alpha 值和 CSS 十六进制颜色将被忽略。

请注意,如果您打算从同一图像中查找多种颜色,则此功能并不是最适合您的需求。如果是这种情况,请在评论中告诉我,我可以进行更改或指导您如何乐观地使用代码。

注意它不太适合一次性使用。但是,如果是这种情况,请更改行 const findPixel = (() => {var findPixel = (() => {使用后删除引用 findpixel = undefined; JS 会清理它所拥有的所有资源。

注意如果您还想获取最接近的找到颜色的实际颜色,那么添加也很简单。在评论中提问。

注意速度相当快(您将很难获得更快的结果),但请注意,对于 4K 及以上的超大图像,可能需要一些时间,并且在非常低端的设备上它可能会导致内存不足错误。如果这是一个问题,那么另一种解决方案是可能的,但速度要慢得多。

关于javascript - 查找图像中的十六进制颜色和 X,Y,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60861356/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com