Colors 使用“制作颜色之间的度量(感知模型)”;差异“;

Colors 使用“制作颜色之间的度量(感知模型)”;差异“;,colors,artificial-intelligence,perception,Colors,Artificial Intelligence,Perception,请看下图。如果你不是色盲,你应该看到一些A和B。图像中有3个A和3个B,它们都有一个共同点:它们的颜色是背景+10%的值,饱和度和色调,按顺序排列。对大多数人来说,中间的字母很难看到——饱和似乎没什么作用 这有点麻烦,因为我正在制作一些字符识别软件,并且我正在根据已知的前景和背景颜色过滤图像。但有时这些距离很近,而图像很嘈杂。为了确定像素是属于字母还是背景,我的程序检查欧几里德RGB距离: (r-fr)*(r-fr) + (g-fg)*(g-fg) + (b-fb)*(b*fb) <

请看下图。如果你不是色盲,你应该看到一些A和B。图像中有3个A和3个B,它们都有一个共同点:它们的颜色是背景+10%的值,饱和度和色调,按顺序排列。对大多数人来说,中间的字母很难看到——饱和似乎没什么作用

这有点麻烦,因为我正在制作一些字符识别软件,并且我正在根据已知的前景背景颜色过滤图像。但有时这些距离很近,而图像很嘈杂。为了确定像素是属于字母还是背景,我的程序检查欧几里德RGB距离:

(r-fr)*(r-fr) + (g-fg)*(g-fg) + (b-fb)*(b*fb) < 
(r-br)*(r-br) + (g-bg)*(g-bg) + (b-bb)*(b*bb) 
(r-fr)*(r-fr)+(g-fg)*(g-fg)+(b-fb)*(b*fb)<
(r-br)*(r-br)+(g-bg)*(g-bg)+(b-bb)*(b*bb)
这是可行的,但对于近距离的背景和前景来说,有时效果相当糟糕


有没有更好的衡量标准?我已经研究了颜色感知模型,但这些模型主要是亮度,而不是我正在寻找的感知差异。也许是一个模型,饱和度较低的有效性,以及某些色调差异也?任何指向一些有趣指标的指针都会非常有用。

正如评论中所提到的,答案是使用感知颜色空间,但我想我会提供一个视觉示例,说明边缘检测在两个颜色空间中的行为。(代码在末尾。)在这两种情况下,对3通道彩色图像执行Sobel边缘检测,然后将结果展平到灰度

RGB空间:

L*a*b空间(图像是对数的,因为第三个字母上的边缘比第一个字母上的边缘更重要,而第一个字母上的边缘比第二个字母上的边缘更重要):

OpenCV C++代码:

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"

using namespace cv;
using namespace std;

void show(const char *name, Mat &img, int dolog=0)
{
  double minVal, maxVal;
  minMaxLoc(img, &minVal, &maxVal);
  cout << name << " " << "minVal : " << minVal << endl << "maxVal : " << maxVal << endl;

  Mat draw;
  if(dolog) {
    Mat shifted, tmp;
    add(img, minVal, shifted);
    log(shifted, tmp);
    minMaxLoc(tmp, &minVal, &maxVal);
    tmp.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
  } else {
    img.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
  }

  namedWindow(name, CV_WINDOW_AUTOSIZE);
  imshow(name, draw);
  imwrite(name, draw);
}

int main( )
{
    Mat src;
    src = imread("AAABBB.png", CV_LOAD_IMAGE_COLOR);
    namedWindow( "Original image", CV_WINDOW_AUTOSIZE );
    imshow( "Original image", src );

    Mat lab, gray;
    cvtColor(src, lab, CV_BGR2Lab);

    Mat sobel_lab, sobel_bgr;
    Sobel(lab, sobel_lab, CV_32F, 1, 0);
    Sobel(src, sobel_bgr, CV_32F, 1, 0);

    Mat bgr_sobel_lab, gray_sobel_lab;
    cvtColor(sobel_lab, bgr_sobel_lab, CV_Lab2BGR);
    show("lab->bgr edges.png", bgr_sobel_lab, 1);
    cvtColor(bgr_sobel_lab, gray_sobel_lab, CV_BGR2GRAY);

    Mat gray_sobel_bgr;
    cvtColor(sobel_bgr, gray_sobel_bgr, CV_BGR2GRAY);

    show("lab edges.png", gray_sobel_lab, 1);
    show("bgr edges.png", gray_sobel_bgr);

    waitKey(0);                                        
    return 0;
} 
#包括“opencv2/core/core.hpp”
#包括“opencv2/highgui/highgui.hpp”
#包括“opencv2/imgproc/imgproc.hpp”
#包括“iostream”
使用名称空间cv;
使用名称空间std;
无效显示(常量字符*名称、Mat和img、int dolog=0)
{
双最小值,最大值;
minMaxLoc(img,&minVal,&maxVal);

你没试过使用任何著名的色差算法吗?另外,你的公式似乎是用RGB颜色空间而不是LAB。谢谢!你的LAB颜色空间参考正是我所需要的,我在这里找到了一些好的代码可以使用。现在我的程序在区分颜色方面做得更好。很高兴我能帮上忙:)我建议你将您的解决方案作为答案发布,以供将来参考。