Skip to main content

Detect colors in images - 20 x faster than Numpy / 430 x faster than PIL

pip install locate-pixelcolor-cpppragma

Tested against Windows 10 / Python 3.10 / Anaconda

Important!

The module imports a function from a compiled .dll (C++). If you get any import errors, install: https://download.visualstudio.microsoft.com/download/pr/8b92f460-7e03-4c75-a139-e264a770758d/26C2C72FBA6438F5E29AF8EBC4826A1E424581B3C446F8C735361F1DB7BEFF72/VC_redist.x64.exe

How to use it in Python

import numpy as np
import cv2
from locate_pixelcolor_cpppragma import search_colors
# 4525 x 6623 x 3 picture https://www.pexels.com/pt-br/foto/foto-da-raposa-sentada-no-chao-2295744/
picx = r"C:\Users\hansc\Downloads\pexels-alex-andrews-2295744.jpg"
pic = cv2.imread(picx)
colors0 = np.array([[255, 255, 255]],dtype=np.uint8)
resus0 = search_colors(pic=pic, colors=colors0, cpus=5)
colors1=np.array([(66,  71,  69),(62,  67,  65),(144, 155, 153),(52,  57,  55),(127, 138, 136),(53,  58,  56),(51,  56,  54),(32,  27,  18),(24,  17,   8),],dtype=np.uint8)
resus1 =  search_colors(pic=pic, colors=colors1, cpus=4)

####################################################################
%timeit resus0 = search_colors(pic=pic, colors=colors0, cpus=5)
23.4 ms ± 40.6 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) # 10.9 ms after last update

b,g,r = pic[...,0],pic[...,1],pic[...,2]
%timeit np.where(((b==255)&(g==255)&(r==255)))
150 ms ± 209 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
####################################################################
%timeit resus1 =  search_colors(pic=pic, colors=colors1, cpus=4)
46.6 ms ± 988 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) # 43.6 after last update

%timeit np.where(((b==66)&(g==71)&(r==69))|((b==62)&(g==67)&(r==65))|((b==144)&(g==155)&(r==153))|((b==52)&(g==57)&(r==55))|((b==127)&(g==138)&(r==136))|((b==53)&(g==58)&(r==56))|((b==51)&(g==56)&(r==54))|((b==32)&(g==27)&(r==18))|((b==24)&(g==17)&(r==8)))
1 s ± 16.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
####################################################################

The C++ Code

#include <omp.h>
#include <atomic>  
std::atomic<int> value(0);
int create_id() {
    return value++;
    }


extern "C" __declspec(dllexport) void colorsearch(unsigned char *pic, unsigned char *colors, int width, int totallengthpic, int totallengthcolor, int *outputx, int *outputy, int *lastresult)
{
    value = 0;
    int counter = 0;

#pragma omp parallel reduction(+ : counter)
    {


        for (int i = 0; i <= totallengthcolor; i += 3)
        {
            int r = colors[i];
            int g = colors[i + 1];
            int b = colors[i + 2];
#pragma omp for schedule(static)            
            for (int j = 0; j <= totallengthpic; j += 3)
            {
                if ((r == pic[j]) && (g == pic[j + 1]) && (b == pic[j + 2]))
                {

#pragma omp critical
                    {
                        int dividend = j / 3;
                        int quotient = dividend / width;
                        int remainder = dividend % width;
                        int upcounter = create_id();
                        outputx[upcounter] = quotient;
                        outputy[upcounter] = remainder;
                        lastresult[0] = upcounter;
                    }
                }
            }
        }
    }
}


extern "C" __declspec(dllexport) void colorsearch2(unsigned char *pic, unsigned char *colors, int width, int totallengthpic, int totallengthcolor, int *outputx, int *outputy, int *lastresult)
{
    value=0;
    int counter = 0;

#pragma omp parallel reduction(+ \
                               : counter)
    {

#pragma omp for schedule(static)
        for (int i = 0; i <= totallengthcolor; i += 3)
        {
        int r = colors[i];
        int g = colors[i + 1];
        int b = colors[i + 2];
            for (int j = 0; j <= totallengthpic; j += 3)
            {
                 if ((r == pic[j]) && (g == pic[j + 1]) && (b == pic[j + 2]))
                {

#pragma omp critical
                    {
                        int dividend = j / 3;
                        int quotient = dividend / width;
                        int remainder = dividend % width;
                        int upcounter = create_id();
                        outputx[upcounter] = quotient;
                        outputy[upcounter] = remainder;
                        lastresult[0] = upcounter;
                    }
                }
            }
        }
    }
}
// Compile:
// cl.exe /std:c++20 /fp:fast /EHsc /MT /Og /Oi /Ot /Oy /Ob3 /GF /Gy /MD /openmp /LD clooppra.cpp /Fe:clooppra.dll
// or
// cl.exe /std:c++20 /fp:fast /EHsc /O2 /MD /openmp /LD clooppra.cpp /Fe:clooppra.dll

Release files for locate-pixelcolor-cpppragma 0.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for locate-pixelcolor-cpppragma 0.12
File Size Uploaded
locate_pixelcolor_cpppragma-0.12.tar.gz 28.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for locate-pixelcolor-cpppragma 0.12
File Interpreter ABI Platform
locate_pixelcolor_cpppragma-0.12-py3-none-any.whl Python 3 none any Details

Total release size: 57.3 kB

Release files / locate_pixelcolor_cpppragma-0.12.tar.gz

Download URL locate_pixelcolor_cpppragma-0.12.tar.gz
Size 28.3 kB
Tags Source
SHA-256 checksum
How to use checksums
0a455a60539d18a2c990e316f656d99dda7b1fb158f771474ade225d1a0b268e
BLAKE2b-256 checksum
How to use checksums
08cc87ba05ad819bbbdc6bad36aac947d0d0cf4e77584e593a283eff8976ece0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.10.10

Release files / locate_pixelcolor_cpppragma-0.12-py3-none-any.whl

Download URL locate_pixelcolor_cpppragma-0.12-py3-none-any.whl
Size 29.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5adcd597795e92b02686c80a45184ca5c0961b72d6f056e1793bb3dc69f3d840
BLAKE2b-256 checksum
How to use checksums
c76c8e30828497338d99b54fa828f0f529400dbcd0b9080cd56a2a6c60b9b617
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.10.10

Release history Release notifications | RSS feed

This release

0.12 This release

2 release files

0.11

2 release files

0.10

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page