Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 提出一种针对大型已知集合的颜色模式匹配算法_C#_Algorithm_Opencv_Hashtable_Knn - Fatal编程技术网

C# 提出一种针对大型已知集合的颜色模式匹配算法

C# 提出一种针对大型已知集合的颜色模式匹配算法,c#,algorithm,opencv,hashtable,knn,C#,Algorithm,Opencv,Hashtable,Knn,我有一个要求,要求将一组颜色值样本与一组已知值进行匹配,以找到精确匹配或在可接受距离内的匹配。我不完全确定什么算法最适合这个,我正在寻找建议 我考虑过使用SQL查询,因为我认为这将是一种简单的方法,但是,理想情况下,这将在应用服务器上的内存中完成,甚至在GPU上完成,以获得最大的速度 示例: 假设我们得到一组三个RGB颜色值,两个蓝色和一个橙色: 样本集: Color 1 Color 2 Color 3 Sample A: [25, 25,

我有一个要求,要求将一组颜色值样本与一组已知值进行匹配,以找到精确匹配或在可接受距离内的匹配。我不完全确定什么算法最适合这个,我正在寻找建议

我考虑过使用SQL查询,因为我认为这将是一种简单的方法,但是,理想情况下,这将在应用服务器上的内存中完成,甚至在GPU上完成,以获得最大的速度

示例

假设我们得到一组三个RGB颜色值,两个蓝色和一个橙色:

样本集:

            Color 1          Color 2       Color 3
Sample A: [25, 25, 25],    [10, 10, 10], [100, 100, 100] 

Sample B: [125, 125, 125], [10, 10, 10], [200, 200, 200] 

Sample C: [13, 87, 255],   [10, 10, 10], [100, 100, 100] 

Sample D: [67, 111, 0],    [10, 10, 10], [200, 200, 200] 

Sample E: [255, 255, 255], [10, 10, 10], [100, 100, 100] 
颜色1:81177206(蓝色)

颜色2:36、70、224(蓝色)

颜色3:255、132、0(橙色)

这组3个颜色值必须与一组更大的颜色值匹配,以查看是否存在这组颜色值,或者3种颜色中的每种颜色都具有相同的精确RGB值,或者如果存在任何图案,其中颜色的RGB值的变化程度可以接受。让我们假设任何RGB组件的值可以高出或低出3位

假设我们要搜索的一大组已知颜色值如下所示:

CREATE TABLE KnownColorSets (
   KC_1_R tinyint NOT NULL,
   KC_1_G tinyint NOT NULL,
   KC_1_B tinyint NOT NULL,
   KC_2_R tinyint NOT NULL,
   KC_2_G tinyint NOT NULL,
   KC_2_B tinyint NOT NULL,
   KC_3_R tinyint NOT NULL,
   KC_3_G tinyint NOT NULL,
   KC_3_B tinyint NOT NULL
)

CREATE TYPE CompareColorSet As TABLE 
(
   CC_1_R tinyint NOT NULL,
   CC_1_G tinyint NOT NULL,
   CC_1_B tinyint NOT NULL,
   CC_2_R tinyint NOT NULL,
   CC_2_G tinyint NOT NULL,
   CC_2_B tinyint NOT NULL,
   CC_3_R tinyint NOT NULL,
   CC_3_G tinyint NOT NULL,
   CC_3_B tinyint NOT NULL
)



CREATE PROCEDURE stpCompareColorSets 
(
    @Exists bit output,
    @CompareColorSet dbo.CompareColorSet readonly
)
AS
  DECLARE @MaxDiviation tinyint = 3 -- This may be taken from a General params table or added as a parameter to the stored procedure
  SET @Exists = 0
  IF EXISTS (
    SELECT 1
    FROM KnownColorSets KC INNER JOIN
    @CompareColorSet CC ON(
      KC_1_R BETWEEN CC_1_R - @MaxDiviation AND CC_1_R - @MaxDiviation
      AND KC_1_G BETWEEN CC_1_G - @MaxDiviation AND CC_1_G - @MaxDiviation
      AND KC_1_B BETWEEN CC_1_B - @MaxDiviation AND CC_1_B - @MaxDiviation

      AND KC_2_R BETWEEN CC_2_R - @MaxDiviation AND CC_2_R - @MaxDiviation
      AND KC_2_G BETWEEN CC_2_G - @MaxDiviation AND CC_2_G - @MaxDiviation
      AND KC_2_B BETWEEN CC_2_B - @MaxDiviation AND CC_2_B - @MaxDiviation

      AND KC_3_R BETWEEN CC_3_R - @MaxDiviation AND CC_3_R - @MaxDiviation
      AND KC_3_G BETWEEN CC_3_G - @MaxDiviation AND CC_3_G - @MaxDiviation
      AND KC_3_B BETWEEN CC_3_B - @MaxDiviation AND CC_3_B - @MaxDiviation
    )
  ) 
  SET @Exists = 1
已知集合:

            Color 1          Color 2       Color 3
Sample A: [25, 25, 25],    [10, 10, 10], [100, 100, 100] 

Sample B: [125, 125, 125], [10, 10, 10], [200, 200, 200] 

Sample C: [13, 87, 255],   [10, 10, 10], [100, 100, 100] 

Sample D: [67, 111, 0],    [10, 10, 10], [200, 200, 200] 

Sample E: [255, 255, 255], [10, 10, 10], [100, 100, 100] 
在这种情况下,当我们对其运行样本集时,我们会发现零匹配,因为没有任何已知颜色的颜色1与样本集的值接近。但是,让我们向已知集添加另一种颜色,该颜色将返回正匹配:

Sample F: [81,177,206], [36, 70, 224], [255, 132, 0]
如果样本F与已知集合中的这些值一起存在,我们将得到一个正的命中,因为它与样本集合中颜色1的RGB值完全相同。此外,我们需要接受RGB值中不同程度的差异,因此以下内容也将返回正点击,因为每个RGB值都在样本集中颜色1值的3位以内:

正面点击数:(记住颜色1是:81177206)

样本F:80,177206(红色通道距离1位)

样本F:81、175204(绿色和蓝色通道相隔2位)

样本F:82179208(3位以内的所有三个通道)

但是,如果距离太远,则无法找到匹配项。任何RGB分量必须在3位以内才能触发阳性结果。因此,如果样本F如下所示,我们将而不是得到一个正结果,因为距离太远:

负面点击:

            Color 1          Color 2       Color 3
Sample A: [25, 25, 25],    [10, 10, 10], [100, 100, 100] 

Sample B: [125, 125, 125], [10, 10, 10], [200, 200, 200] 

Sample C: [13, 87, 255],   [10, 10, 10], [100, 100, 100] 

Sample D: [67, 111, 0],    [10, 10, 10], [200, 200, 200] 

Sample E: [255, 255, 255], [10, 10, 10], [100, 100, 100] 
样本F:85,177206(红色通道距离为4位)

样本F:81,170,206(绿色通道距离7位)

样本F:81177,200(蓝色通道距离6位)

到目前为止,我们只考虑了样本集中的颜色1。但是,该要求需要考虑整个样本集。因此,如果没有颜色匹配的1可以找到正匹配,那么我们就假设没有匹配,并且不考虑样本集的颜色2和3。p> 但是,如果我们发现颜色1的结果为正,比如说80177206,它在红色通道80和81中只差1位,那么我们继续处理颜色2,如果我们发现颜色2的结果为正,那么我们处理颜色3,依此类推

你对最适合这个问题的算法有什么建议?我需要的东西,将允许已知的设置规模非常大,没有太多的性能打击。在已知的样本集中,按比例可能会有100多万个样本

我考虑使用哈希表,每种颜色一个哈希表来构造已知的集合。所以我可以测试颜色1上的匹配,如果找到,测试颜色2的哈希表,当我没有找到更多的匹配时停止。如果我通过了所有3种颜色/哈希表的正面点击,那么我会有一个整体的正面匹配,否则我不会。但是,这种方法不考虑每种颜色的每个RGB通道中所需的变化。将有太多的组合,不允许构建哈希表来容纳所有的组合


提前感谢您,感谢您阅读本文

保留一个已排序的列表。使用稳定排序对其进行三次排序,先按B排序,然后按G排序,再按R排序。这样就可以按RGB顺序对其进行排序。根据您的输入,通过二进制搜索找到第一个和最后一个可接受的R的索引。然后在该范围内搜索可接受的G,然后在缩小的范围内再次搜索B。整个事情应该是O(lgN)

-- 除非我遗漏了一些东西,否则这个解决方案可以推广到匹配一组3种颜色,或10种颜色或k种颜色。在颜色集列表中生成索引数组。要准备,请按上述方法对索引进行3*k次的稳定排序。要查找,请按相反顺序执行3*k二进制搜索


(这假设颜色固定在列中。如果没有,您仍然可以使用此方法,但索引列表变为N*k大小:它需要A1、A2、A3的条目。最后添加一个检查,确保您已匹配每列中的一个。)

根据您在问题中的描述和评论中的对话,为什么不使用简单的存储过程和用户定义的类型?有了适当的索引,就不会有性能问题。假设要比较的颜色集包含多组3种颜色,我可能会这样做:

CREATE TABLE KnownColorSets (
   KC_1_R tinyint NOT NULL,
   KC_1_G tinyint NOT NULL,
   KC_1_B tinyint NOT NULL,
   KC_2_R tinyint NOT NULL,
   KC_2_G tinyint NOT NULL,
   KC_2_B tinyint NOT NULL,
   KC_3_R tinyint NOT NULL,
   KC_3_G tinyint NOT NULL,
   KC_3_B tinyint NOT NULL
)

CREATE TYPE CompareColorSet As TABLE 
(
   CC_1_R tinyint NOT NULL,
   CC_1_G tinyint NOT NULL,
   CC_1_B tinyint NOT NULL,
   CC_2_R tinyint NOT NULL,
   CC_2_G tinyint NOT NULL,
   CC_2_B tinyint NOT NULL,
   CC_3_R tinyint NOT NULL,
   CC_3_G tinyint NOT NULL,
   CC_3_B tinyint NOT NULL
)



CREATE PROCEDURE stpCompareColorSets 
(
    @Exists bit output,
    @CompareColorSet dbo.CompareColorSet readonly
)
AS
  DECLARE @MaxDiviation tinyint = 3 -- This may be taken from a General params table or added as a parameter to the stored procedure
  SET @Exists = 0
  IF EXISTS (
    SELECT 1
    FROM KnownColorSets KC INNER JOIN
    @CompareColorSet CC ON(
      KC_1_R BETWEEN CC_1_R - @MaxDiviation AND CC_1_R - @MaxDiviation
      AND KC_1_G BETWEEN CC_1_G - @MaxDiviation AND CC_1_G - @MaxDiviation
      AND KC_1_B BETWEEN CC_1_B - @MaxDiviation AND CC_1_B - @MaxDiviation

      AND KC_2_R BETWEEN CC_2_R - @MaxDiviation AND CC_2_R - @MaxDiviation
      AND KC_2_G BETWEEN CC_2_G - @MaxDiviation AND CC_2_G - @MaxDiviation
      AND KC_2_B BETWEEN CC_2_B - @MaxDiviation AND CC_2_B - @MaxDiviation

      AND KC_3_R BETWEEN CC_3_R - @MaxDiviation AND CC_3_R - @MaxDiviation
      AND KC_3_G BETWEEN CC_3_G - @MaxDiviation AND CC_3_G - @MaxDiviation
      AND KC_3_B BETWEEN CC_3_B - @MaxDiviation AND CC_3_B - @MaxDiviation
    )
  ) 
  SET @Exists = 1

最后,在试验了SQL和GPU编程(Cudafy)之后,最快、最简单、最可调试的解决方案是使用Parallel.For()简单地迭代数据。这种方法在18ms内处理了150万个样本(总字节数为90M)

3是允许的累积偏差,还是R、G、B值的累积偏差?是集合中每个颜色内的每个RGB值的累积偏差。这并不是一个文化上的偏差,尽管把它作为一个例子也许不是一个坏主意