在图像中查找十六进制颜色和X,Y [英] Find Hex Colors and X,Y in Images

查看:60
本文介绍了在图像中查找十六进制颜色和X,Y的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to find all the hex colors in an image and if possible, circle or highlight the X, Y position of where the hex color(s) are. My current code is attempting to find all colors and almost crashes my browser and my attempt to find the X,Y coordinates of each image isn't going good either.

我有两个函数可以做不同的事情,这是我尝试使用的功能,以举例说明尝试过的事情……任何帮助都将是非常棒的!

I have two functions doing different things, it's what I have tried to work with to give an example of what has been attempted... Any help would be great!

任何帮助都会很棒!

<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>");     
                    }    

        }

推荐答案

必须检查所有像素

要找到与颜色匹配的像素,在最坏的情况下(该颜色的像素不在图像中)将要求您跨过图像中的每个像素.

Must check all pixels

To find a pixel that matches a color will require, in the worst case (pixel of that color not in image), that you step over every pixel in the image.

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

Converting every pixel to a DOM string is about the worst way to do it, as DOM string use a lot of memory and CPU overhead, especially if instantiated using jQuery (which has its own additional baggage)

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

To find the pixel you need only check each pixels color data against the HEX value. You convert the hex value to an array of 3 Bytes.

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

The following function will convert from CSS Hex formats "#HHH" "#HHHH", "#HHHHHH" and "#HHHHHHHH" ignoring the alpha part if included, to an array of integers 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)];
}

找到像素

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

Finding the pixel

I do not know how you plan to use such a feature so the example below is a general purpose method that will help and can be modified as needed

即使没有完美匹配,如果您允许它也会始终找到一个像素.它通过找到与所需颜色最接近的颜色来做到这一点.

It will always find a pixel if you let it even if there is no perfect match. It does this by finding the closest color to the color you are looking for.

之所以找到最匹配的原因是,当您将图像绘制到2D画布上时,如果图像具有透明像素(预乘alpha),则像素值会稍作修改

The reason that of finds the closest match is that when you draw an image onto a 2D canvas the pixel values are modified slightly if the image has transparent pixels (pre-multiplied alpha)

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

The function finds the pixel by measuring the spacial distance between the pixel and the hex color (simple geometry Pythagoras). The closest color is the one that is the smallest distance.

它将返回对象

{
   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

If the image is tainted (cross origin, local device storage), or you pass something that can not be converted to pixels the function will return undefined

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

The function keeps a canvas that it uses to get pixel data as it assumes that it will be use many times. If the image is tainted it will catch the error (add a warning to the console), cleanup the tainted canvas and be ready for another image.

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

To use the function add it to your code base, it will setup automatically.

获取图像和十六进制值,然后使用 image ,CSS hex 颜色以及可选的颜色匹配阈值距离调用函数.

Get an image and a hex value and call the function with the image, CSS hex color, and optionally the threshold distance for the color match.

例如找到#FF0000的完全匹配

Eg find exact match for #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十六进制颜色将被忽略.

Note Going by the code in the your question the alpha value of the image and CSS hex color is ignored.

注意,如果您打算从同一张图片中找到许多颜色,则此功能并非最适合您的需求.如果是这种情况,请在评论中告诉我,我可以进行更改或指示您如何优化此类用途的代码.

Note that if you intend to find many colors from the same image this function is not the best suited for you needs. If this is the case let me know in the comment and I can make changes or instruct you how to optimism the code for such uses.

注意:它不太适合仅一次性使用.但是,在这种情况下,将行 const findPixel =(()=> {更改为 var findPixel =(()=> {删除引用 findpixel = undefined; ,然后JS将清除其拥有的所有资源.

Note It is not well suited for single use only. However if this is the case change the line const findPixel = (() => { to var findPixel = (() => { and after you have used it remove the reference findpixel = undefined; and JS will clean up any resources it holds.

注意,如果您还想获取最接近的发现颜色的实际颜色,那么该颜色也很容易添加.在评论中提问.

Note If you also want to get the actual color of the closest found color that is trivial to add as well. Ask in the comments.

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

Note It is reasonably quick (you will be hard pressed to get a quicker result) but be warned that for very large images 4K and above it may take a bit, and on very low end devices it may cause a out of memory error. If this is a problem then another solution is possible but is far slower.

这篇关于在图像中查找十六进制颜色和X,Y的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆