Colors 使用“制作颜色之间的度量(感知模型)”;差异“;
请看下图。如果你不是色盲,你应该看到一些A和B。图像中有3个A和3个B,它们都有一个共同点:它们的颜色是背景+10%的值,饱和度和色调,按顺序排列。对大多数人来说,中间的字母很难看到——饱和似乎没什么作用 这有点麻烦,因为我正在制作一些字符识别软件,并且我正在根据已知的前景和背景颜色过滤图像。但有时这些距离很近,而图像很嘈杂。为了确定像素是属于字母还是背景,我的程序检查欧几里德RGB距离: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) <
(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颜色空间参考正是我所需要的,我在这里找到了一些好的代码可以使用。现在我的程序在区分颜色方面做得更好。很高兴我能帮上忙:)我建议你将您的解决方案作为答案发布,以供将来参考。