2

看看下面的图片。如果你不是色盲,你应该看到一些 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) 

这可以正常工作,但对于近距离的背景和前景,有时效果会很差。

是否有一些更好的指标可供寻找?我研究了颜色感知模型,但那些主要是模型亮度而不是我正在寻找的感知差异。也许是一种将饱和度建模为不太有效的模型,以及某些色调差异?任何指向一些有趣指标的指针都会非常有用。

4

1 回答 1

2

正如评论中提到的,答案是使用感知色彩空间,但我想我会拼凑一个视觉示例,说明边缘检测在两个色彩空间中的行为方式。(代码在最后。)在这两种情况下,都是对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;
} 
于 2015-05-29T23:30:36.730 回答