简体   繁体   English

查找单个 rgb 值是否落在数组中任何 rgb 值的阈值内 - javascript

[英]Finding if a single rgb value falls within a threshold of any rgb value in an array - javascript

I would appreciate some advice on creating a function to compare a single RGB value against an array of RGB values and determine if it falls within a threshold.我将不胜感激关于创建 function 以将单个 RGB 值与 RGB 值数组进行比较并确定它是否在阈值范围内的建议。 This is done in vanilla javascript using the HTML5 canvas element.这是在香草 javascript 中使用 HTML5 canvas 元素完成的。

My first attempt:我的第一次尝试:

var colorArray = [  //rgb values to search through
[212, 35, 96],
[200, 200, 150],
[100, 100, 75]
];

var threshold = 15;   //the threshold

//Given a canvas with an image drawn on it
var pixelData = ctx.getImageData(0, 0, canvas.width, canvas.height); // get the canvas pixel data

for(var row = 0; row < canvas.height; row++){   //stepping through the pixels

    for (var col = 0, index = 0, colorTotal = 0; col < canvas.width; col++){
        
        index = (col + (row * canvas.width)) * 4;
        colorTotal = pixelData.data[index] + pixelData.data[index + 1] + pixelData.data[index + 2];  //add the rgb values of the current pixel

        for(var i = 0, pixelColorTotal = 0, result = 0; i < colorArray.length; i++){   //stepping through the colorArray

            pixelColorTotal = colorArray[i] [0] + colorArray[i] [1] + colorArray[i] [2];  //add the rgb values of the current array element
            result = Math.abs(colorTotal - pixelColorTotal);  //find the difference between the color totals

            if(result < threshold){
               //..do something we've breached the threshold
            }
        }
    }
}

That does not work so well because for example: [255, 0, 50] and [50, 255, 0] are not even close to the same color yet they would trip the threshold.这不是很好,因为例如:[255, 0, 50] 和 [50, 255, 0] 甚至不接近相同的颜色,但它们会触发阈值。

My 2nd attempt:我的第二次尝试:

var colorArray = [  //rgb values to search through
[212, 35, 96],
[200, 200, 150],
[100, 100, 75]
];

var threshold = 15;   //the threshold

//Given a canvas with an image drawn on it
var pixelData = ctx.getImageData(0, 0, canvas.width, canvas.height); // get the canvas pixel data

for(var row = 0; row < canvas.height; row++){   //stepping through the pixels

    for (var col = 0, index = 0; col < canvas.width; col++){
        
        index = (col + (row * canvas.width)) * 4;

        for(var i = 0, result = 0; i < colorArray.length; i++){   //stepping through the colorArray

            result = Math.abs(pixelData.data[index] - colorArray[i] [0]);   //load red difference
            if(result >= threshold){       //check the red channel to see if it exceeds threshold

                result = Math.abs(pixelData.data[index + 1] - colorArray[i] [1]);   //load green difference
                if(result >= threshold){       //check the green channel to see if it exceeds threshold

                     result = Math.abs(pixelData.data[index + 2] - colorArray[i] [2]);   //load blue difference
                     if(result >= threshold){       //check the green channel to see if it exceeds threshold

                         //do something we have passed all the threshold checks

                     }

                }
            }
        }
    }
}

That is better but very inefficient.那更好但效率很低。

Are there any better ideas out there?有没有更好的主意? Thanks for reading.谢谢阅读。

I'm not 100% sure what you want, so let me know if I'm going in the wrong direction.我不是 100% 确定你想要什么,所以如果我走错了方向,请告诉我。

function withinThreshold(colorArr, inputArr, threshold){
    let maxThreshold = threshold;
    let minThreshold = threshold * -1;
    for(var i = 0; i < colorArr.length; i++){
        let rDiff = colorArr[i][0] - inputArr[0];
        let gDiff = colorArr[i][1] - inputArr[1];
        let bDiff = colorArr[i][2] - inputArr[2];
        if(rDiff > minThreshold && rDiff < maxThreshold &&
           gDiff > minThreshold && gDiff < maxThreshold &&
           bDiff > minThreshold && gDiff < maxThreshold){
             return i
        }
    }
    return -1
}

var colorArray = [  //rgb values to search through
    [212, 35, 96],
    [200, 200, 150],
    [100, 100, 75]
];
var threshold = 15;

for(var row = 0; row < canvas.height; row++){
    for (var col = 0; col < canvas.width; col++){
        let pixel = ctx.getImageData(row, col, 1, 1);
        let match = withinThreshold(colorArray, pixel, threshold);
        if(match === -1){
            console.log('no match found');
        }else{
            console.log('match found! index:',match);
        }
        // I made it like indexOf, it will return the matching index of colorArr.
        // You can simplify it like this:
        /*
            if(match > -1){
                console.log('match found');
            }
        */
    }
}

Also don't forget that getImageData will most likely return 4 digit array [r,g,b,a], unless you changed the settings to not allow alpha.也不要忘记 getImageData 很可能会返回 4 位数组 [r,g,b,a],除非您将设置更改为不允许 alpha。

Also I made it so it individually grabs the pixel data it needs.我也做了它,所以它单独获取它需要的像素数据。 This way in the future you can refine it down to a specific location without having the check everything.这样,将来您可以将其细化到特定位置,而无需检查所有内容。 Simply by changing the row and canvas.width to 10 and 20. This way you can save processing for only the changed area.只需将canvas.width更改为 10 和 20。这样您就可以只对更改的区域保存处理。 You can also do it with col and canvas.height to shrink it down even more.您也可以使用colcanvas.height来缩小它。

I made a few canvas rendering engines, so I've ran into performance issues and had to deal with a lot of optimising.我做了几个 canvas 渲染引擎,所以我遇到了性能问题并且不得不处理很多优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM