使用 C++ 和 openframeworks 的 Color 图像检索系统

2023-12-31

我正在用 C++ 和 openFrameworks 编写一个程序,希望能够通过颜色匹配来实现图像检索系统。我有一个算法可以通过 RGB 值在数据库中查找匹配项。例如,如果我的计算机上有一个包含 1000 张图片的数据库,并且我有一个查询 rgb 值 255,0,0,则程序将查找 1000 张图片并找到最接近的匹配项。然而,我的问题是我希望它也能在网络上查找匹配项。我一直在尝试寻找如何从网站获取图像,但是,如果您不知道图像的具体网址,则很难获取数据。也许有人了解如何获取网站上的图像?理想情况下,程序将在指定的网站上搜索每个网页中的图像,然后将每个图像与查询进行比较并输出最接近的匹配。


正如我在评论中提到的,这是从 RGB 颜色空间转换为 L 的问题ab* 颜色空间并使用与数据库中图像的平均颜色的欧几里德距离。

Here's a basic demo: image search by colour

#include "testApp.h"

//ported from http://cookbooks.adobe.com/post_Useful_color_equations__RGB_to_LAB_converter-14227.html
struct Color{
    float R,G,B,X,Y,Z,L,a,b;
};

#define REF_X 95.047; // Observer= 2°, Illuminant= D65
#define REF_Y 100.000;
#define REF_Z 108.883;

Color rgb2xyz(int R,int G,int B){
    float r = R / 255.0;
    float g = G / 255.0;
    float b = B / 255.0;

    if (r > 0.04045){ r = pow((r + 0.055) / 1.055, 2.4); }
    else { r = r / 12.92; }
    if ( g > 0.04045){ g = pow((g + 0.055) / 1.055, 2.4); }
    else { g = g / 12.92; }
    if (b > 0.04045){ b = pow((b + 0.055) / 1.055, 2.4); }
    else {  b = b / 12.92; }

    r = r * 100;
    g = g * 100;
    b = b * 100;
    //Observer. = 2°, Illuminant = D65
    Color xyz;
    xyz.X = r * 0.4124 + g * 0.3576 + b * 0.1805;
    xyz.Y = r * 0.2126 + g * 0.7152 + b * 0.0722;
    xyz.Z = r * 0.0193 + g * 0.1192 + b * 0.9505;
    return xyz;
}
Color xyz2lab(float X,float Y, float Z){
    float x = X / REF_X;
    float y = Y / REF_X;
    float z = Z / REF_X;

    if ( x > 0.008856 ) { x = pow( x , .3333333333f ); }
    else { x = ( 7.787 * x ) + ( 16/116.0 ); }
    if ( y > 0.008856 ) { y = pow( y , .3333333333f ); }
    else { y = ( 7.787 * y ) + ( 16/116.0 ); }
    if ( z > 0.008856 ) { z = pow( z , .3333333333f ); }
    else { z = ( 7.787 * z ) + ( 16/116.0 ); }

    Color lab;
    lab.L = ( 116 * y ) - 16;
    lab.a = 500 * ( x - y );
    lab.b = 200 * ( y - z );
    return lab;
}
Color lab2xyz(float l, float a, float b){
    float y = (l + 16) / 116;
    float x = a / 500 + y;
    float z = y - b / 200;

    if ( pow( y , 3 ) > 0.008856 ) { y = pow( y , 3 ); }
    else { y = ( y - 16 / 116 ) / 7.787; }
    if ( pow( x , 3 ) > 0.008856 ) { x = pow( x , 3 ); }
    else { x = ( x - 16 / 116 ) / 7.787; }
    if ( pow( z , 3 ) > 0.008856 ) { z = pow( z , 3 ); }
    else { z = ( z - 16 / 116 ) / 7.787; }

    Color xyz;
    xyz.X = x * REF_X;
    xyz.Y = y * REF_Y;
    xyz.Z = z * REF_Z;
    return xyz;
}
Color xyz2rgb(float X,float Y,float Z){
    //X from 0 to  95.047      (Observer = 2°, Illuminant = D65)
    //Y from 0 to 100.000
    //Z from 0 to 108.883
    X = ofClamp(X, 0, 95.047);

    float x = X * .01;
    float y = Y * .01;
    float z = Z * .01;

    float r = x * 3.2406 + y * -1.5372 + z * -0.4986;
    float g = x * -0.9689 + y * 1.8758 + z * 0.0415;
    float b = x * 0.0557 + y * -0.2040 + z * 1.0570;

    if ( r > 0.0031308 ) { r = 1.055 * pow( r , ( 1 / 2.4f ) ) - 0.055; }
    else { r = 12.92 * r; }
    if ( g > 0.0031308 ) { g = 1.055 * pow( g , ( 1 / 2.4f ) ) - 0.055; }
    else { g = 12.92 * g; }
    if ( b > 0.0031308 ) { b = 1.055 * pow( b , ( 1 / 2.4f ) ) - 0.055; }
    else { b = 12.92 * b; }

    Color rgb;
    rgb.R = round( r * 255 );
    rgb.G = round( g * 255 );
    rgb.B = round( b * 255 );
    return rgb;
}
Color rgb2lab(int R,int G,int B){
    Color xyz = rgb2xyz(R, G, B);
    return xyz2lab(xyz.X, xyz.Y, xyz.Z);
}
Color lab2rgb(int L,int a,int b){
    Color xyz = lab2xyz(L, a, b);
    return xyz2rgb(xyz.X, xyz.Y, xyz.Z);
}

Color getAverage(ofImage img){
    Color avg;
    avg.L = avg.a = avg.b = 0;

    int total = img.width * img.height;
    for(int y = 0 ; y < img.height; y++){
        for(int x = 0 ; x < img.width; x++){
            ofColor c = img.getColor(x, y);
            Color lab = rgb2lab(c.r,c.g,c.b);
            avg.L += lab.L;
            avg.a += lab.a;
            avg.b += lab.b;
        }
    }

    avg.L /= total;
    avg.a /= total;
    avg.b /= total;
    return avg;
}
ofImage images[6];
Color   averages[6];
ofColor averagesRGB[6];

ofImage colorPicker;
ofColor searchClr;

int closestId = -1;

//--------------------------------------------------------------
void testApp::setup(){
    colorPicker.loadImage("colormap.gif");

    images[0].loadImage("red.jpg");
    images[1].loadImage("green.jpg");
    images[2].loadImage("blue.jpg");
    images[3].loadImage("cyan.jpg");
    images[4].loadImage("magenta.jpg");
    images[5].loadImage("yellow.jpg");

    for(int i = 0 ;  i < 6; i++){
        averages[i] = getAverage(images[i]);
        Color avgRGB = lab2rgb(averages[i].L, averages[i].a, averages[i].b);
        averagesRGB[i] = ofColor(avgRGB.R,avgRGB.G,avgRGB.B);
    }

}

//--------------------------------------------------------------
void testApp::update(){
    //pick a colour
    searchClr = colorPicker.getColor(mouseX,mouseY-500);
    //find closest - might want to that on an event
    Color searchLab = rgb2lab(searchClr.r, searchClr.g, searchClr.b);
    float minDist = 10000000;
    for(int i = 0 ; i < 6; i++){
        Color Lab = averages[i];
        float dL = Lab.L - searchLab.L;
        float da = Lab.a - searchLab.a;
        float db = Lab.b - searchLab.b;
        float dist = sqrt(dL*dL + da*da + db*db);
        if(dist < minDist){
            minDist = dist;
            closestId = i;
        }
    }
}

//--------------------------------------------------------------
void testApp::draw(){
    for(int i = 0 ;  i < 6; i++){
        //indexed image
        images[i].draw(images[i].width * i, 0);
        //average colour
        ofPushStyle();
        ofSetColor(averagesRGB[i]);
        ofRect(images[i].width * i, images[i].height, images[i].width, images[i].width);
        ofPopStyle();
    }
    ofPushStyle();
    ofSetColor(searchClr);
    ofRect(200,500,200,200);
    ofPopStyle();
    colorPicker.draw(0,500);
    if(closestId >= 0){
        images[closestId].draw(400, 500);
    }
}

//--------------------------------------------------------------
void testApp::keyPressed(int key){

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){ 

}

编码风格并不出色,但它只是为了说明这个想法。当然,您需要首先从 url 加载图像并在 L 中索引平均颜色ab* 代表数据库中的每个(运行时或其他情况下的向量)。 上面的代码也可以作为Xcode项目 http://lifesine.eu/so/LABTest.zip

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 C++ 和 openframeworks 的 Color 图像检索系统 的相关文章

  • JSON.Net 反序列化返回“null”

    我正在使用 JSON Net 反序列化 JSON 字符串 JSON 字符串是 string testJson Fruits Apple color red size round Orange Pro
  • 如何使用 ASP.NET MVC 编辑多选列表?

    我想编辑一个如下所示的对象 我希望用 UsersGrossList 中的一个或多个用户填充 UsersSelectedList 使用 mvc 中的标准编辑视图 我只得到映射的字符串和布尔值 下面未显示 我在 google 上找到的许多示例都
  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • C free() 是如何工作的? [复制]

    这个问题在这里已经有答案了 可能的重复 malloc 和 free 如何工作 https stackoverflow com questions 1119134 how malloc and free work include
  • 客户端应用程序立即对数据库中的更新做出反应的最佳方式是什么?

    对数据库中的数据更新做出立即反应的最佳方法是什么 我能立即想到的最简单的方法是一个线程 它检查数据库中某些数据的特定更改 并持续等待在某个预定义的时间长度内再次检查它 这个解决方案对我来说似乎是浪费和次优的 所以我想知道是否有更好的方法 我
  • 司机和提供商之间的区别

    数据库中的驱动程序和提供程序有什么区别 有没有解释一下 不胜感激 样本 ADO NET driver for MySQL vs providerName System Data EntityClient 来自 MSDN 论坛 驱动程序是安装
  • 将设置函数(setter)标记为 constexpr 的目的是什么? [复制]

    这个问题在这里已经有答案了 我无法理解将 setter 函数标记为的目的constexpr 自 C 14 起这是允许的 我的误解来自以下情况 我使用 constexpr c tor 声明一个类 并且我将通过创建该类的 constexpr 实
  • 在 ASP.NET MVC 中将模型从视图传递到控制器

    我正在 ASP NET MVC 中开发我的第一个应用程序 但遇到了一个我无法解决的问题 即使在阅读了整个互联网之后也是如此 因此 我有几个使用视图模型创建的视图 它们是报告 这些视图模型是根据用户选择标准填充的 我正在尝试构建一种接受模型并
  • 如何以编程方式播放 16 位 pcm 数组 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有一个包含 16 位 pcm 值的短 数组 我希望能够在不添加任何标题 也不将任何文件保存到内存的情况下播放它 我知道我可能需要一个提供
  • 为什么需要数字后缀?

    C 语言 我确信还有其他语言 需要在数字文字末尾添加后缀 这些后缀指示文字的类型 例如 5m是一个小数 5f是一个浮点数 我的问题是 这些后缀真的有必要吗 或者是否可以从上下文中推断出文字的类型 例如 代码decimal d 5 0应该推断
  • 有什么方法可以重载 C# 中的扩展方法吗?

    我有以下模型模式 public abstract class PARENTCLASS public class CHILD A CLASS PARENTCLASS public static class EXTENSION public s
  • Xamarin - SignalR 挂在连接上

    我正在尝试将我的 Xamarin 应用程序连接到托管在 Azure 上的 SignalR 后端 我遇到的问题是每次我在 HubConnection 上调用 StartAsync 时 它都会挂起客户端并且请求永远不会完成 我尝试通过应用程序进
  • Resharper:IEnumerable 的可能多重枚举

    我正在使用新的 Resharper 版本 6 在我的代码中的几个地方 它给一些文本加了下划线 并警告我可能存在IEnumerable 可能的多重枚举 我理解这意味着什么 并在适当的情况下采纳了建议 但在某些情况下 我不确定这实际上是一个大问
  • 使用 OleDbCommandBuilder 时访问 SQL 语法错误

    我要在 C 中使用 OleDbDataAdapter 在 Access 数据库中插入数据 但收到错误消息INSERT INTO 命令中的语法错误 BackgroundWorker worker new BackgroundWorker Ol
  • C++ 到 C# 事件处理

    所以我有我的C WinForm 应用程序 我从中调用我的C CLI MFC dll图书馆 但也有一些events在我的 C 库上 甚至此事件也发生在该库的本机 非 CLI 部分 我需要从我的 C 应用程序调用一些代码 并获取一些有关此事件的
  • C 语言中的 Alpha 混合 2 RGBA 颜色[重复]

    这个问题在这里已经有答案了 可能的重复 如何快速进行阿尔法混合 https stackoverflow com questions 1102692 how to do alpha blend fast 对 2 个 RGBA 整数 颜色进行
  • 无法识别解决方案文件夹中的 Visual Studio 2017 Nuget.config

    我在使用 Visual Studio 2017 时遇到问题 新的解决方案不断引用 C Users yopa AppData Roaming NuGet Nuget config 中意外位置的 Nuget config 文件 我已将 nuge
  • 这种尺寸对齐是如何工作的

    对于所提供的评论 我无法理解以下代码 这段代码的作用是什么 以及等效的代码是什么8 aligned segment size must be 4 aligned attr gt options ssize 3 Here ssize is o
  • 使用 C# 动态创建按钮并按预定义的顺序放置它们

    NET 4 5 C 创建 Windows 窗体 我想动态创建和添加按钮并为其分配单击事件 但希望它们以特定的方式动态放置 就像图像一样 我的问题是如何以上述方式动态放置按钮 即 4x4 格式 一行 4 个按钮 4 列 但行数不受限制 是否可
  • 嵌入式二进制资源 - 如何枚举嵌入的图像文件?

    我按照中的说明进行操作这本书 http www apress com book view 9781430225492 关于资源等的章节 我不太明白的是 如何替换它 images Add new BitmapImage new Uri Ima

随机推荐