2015-04-15 2 views
2

J'ai un problème intéressant. Étant donné une valeur de couleur RVB de pixel (un vecteur, 255 255 255) et une table de base de données de tous les vecteurs historiques connus (couleurs), quel est le moyen le plus efficace/le plus rapide de trouver une correspondance dans le tableau? Par exemple, disons que j'ai un bleu clair (30,144,255) et une table pleine de milliers d'autres couleurs, (mais pas une correspondance exacte avec le bleu ci-dessus) - comment puis-je construire une requête sql pour me trouver le plus proche rencontre? Idéalement, si nous recherchions une correspondance exacte, alors la requête ne retournerait rien mais dans cet exemple le bleu (30,144,255) n'est pas dans la table, donc nous aurions besoin d'un certain degré de tolérance et/ou de distance acceptable de la vecteur fourni. Donc, nous pourrions dire, trouvez-moi un match dans n degrés/pourcentage/quoi que ce soit et nous pourrions ajuster cette tolérance au goût. J'ai vu une logique comme celle-ci exprimée en C#, C++, etc. mais idéalement, je voudrais compenser cela à la base de données et je ne sais pas comment l'exprimer de la manière la plus efficace/la plus rapide.Trouver la correspondance la plus proche au vecteur (RVB) avec une tolérance réglable en SQL?

Merci d'avance!

Répondre

0

pas 100% sûr pourquoi vous faites cela, ou si je comprends bien, mais que vous avez une table avec des valeurs RVB, soit ...

CREATE TABLE Colors (R int, G int, B int); 

Alors, vous voulez trouver quelle ligne est " le plus proche » de la couleur exemple (dire R = 128, G = 54, B = 13), vous pouvez trouver le dossier avec la plus petite somme des différences absolues, par exemple ...

SELECT R, G, B, ABS(R - 128) + ABS(G - 54) + ABS(B - 13) FROM Colors ORDER BY 4 LIMIT 1 

est-ce que vous voulez dire ?

1

Les couleurs peuvent être mathématiquement proches dans l'espace RVB sans être perçues comme proches par les humains. Si vous mappez d'abord l'espace colorimétrique RVB à YUV, il s'alignera mieux avec la vision humaine.

DECLARE @R int, @G int, @B int 

SELECT TOP(1) 
    R,G,B 
,distance = ([email protected])*([email protected])+([email protected])*([email protected])+([email protected])*([email protected]) 
FROM MyTable AS rgb 
CROSS APPLY (
    SELECT 
    Y =    (0.299*R + 0.587*G + 0.114*B) 
    ,U = 0.492 * (B - (0.299*R + 0.587*G + 0.114*B)) 
    ,V = 0.877 * (B - (0.299*R + 0.587*G + 0.114*B)) 
    ,iY =    (0.299*@R + 0.587*@G + 0.114*@B) 
    ,iU = 0.492 * (@B - (0.299*@R + 0.587*@G + 0.114*@B)) 
    ,iV = 0.877 * (@B - (0.299*@R + 0.587*@G + 0.114*@B)) 
) yuv 
ORDER BY distance 
+0

Merci - dans ce cas, comparer RVB devrait suffire car les yeux humains ne sont pas impliqués. – znelson

+0

Vous aurez toujours envie de trier sur la distance euclidienne '(x-x1)^2 + (y-y1)^2 + (z-z1)^2' au lieu de la distance de Manhattan' | x-x1 | + | y-y1 | + | z-z1 | ' – Anon