4

我在一个房地产网站上工作,我想编写一个程序来确定(分类)图像是平面图还是公司徽标。

因为我用 php 编写,所以我更喜欢 php 解决方案,但任何 c++ 或 opencv 解决方案也可以。

平面图样本:

替代文字 http://www.rentingtime.com/uploads/listing/l0050/0000050930/68614.jpg

替代文字 http://www.rentingtime.com/uploads/listing/l0031/0000031701/44199.jpg

标志样本:

替代文字 http://www.rentingtime.com/uploads/listing/l0091/0000091285/95205.jpg

4

9 回答 9

6

与往常一样,有一个用于此的内置 PHP 函数。只是开玩笑。=)

我见过的所有平面图都是单色的,我认为您可以使用颜色的数量和颜色饱和度来很好地猜测图像是徽标还是平面图。

例如:is the image has less than 2 or 3 colors is a floor plan.

例如:if the sum / average of the saturation is less than X it's a floor plan.

黑色和白色(以及平面图中使用的其他类似颜色)的饱和度为零或非常接近于零,而徽标往往更具视觉吸引力,因此使用更饱和的颜色。

这是一个计算 Hex RGB 颜色饱和度的简单函数:

function Saturation($color)
{
    $color = array_map('hexdec', str_split($color, 2));

    if (max($color) > 0)
    {
        return (max($color) - min($color)) / max($color);
    }

    return 0;
}

var_dump(Saturation('000000')); // black    0.0000000000000000
var_dump(Saturation('FFFFFF')); // white    0.0000000000000000
var_dump(Saturation('818185')); // grey     0.0300751879699249
var_dump(Saturation('5B9058')); // green    0.3888888888888889
var_dump(Saturation('DE1C5F')); // pink     0.8738738738738738
var_dump(Saturation('FE7A15')); // orange   0.9173228346456692
var_dump(Saturation('FF0000')); // red      1.0000000000000000
var_dump(Saturation('80FF80')); // ---      0.4980392156862745
var_dump(Saturation('000080')); // ---      1.0000000000000000

使用imagecolorat()imagecolorsforindex()您可以实现一个简单的函数,该函数循环遍历图像的所有像素并求和/计算饱和度的平均值。如果图像的饱和度高于您定义的自定义阈值,则可以假定图像是徽标。

你不应该忘记的一件事是,具有更高分辨率的图像通常会有更多的饱和度(更多的像素总和),所以为了这个算法和你的服务器性能,调整所有图像的大小是明智的。图像以通用分辨率(例如 100x100 或 50x50)对它们进行分类,一旦分类,您就可以使用原始(未调整大小的)图像。

我用您提供的图像做了一个简单的测试,这是我使用的代码:

$images = array('./44199.jpg', './68614.jpg', './95205.jpg', './logo.png', './logo.gif');

foreach ($images as $image)
{
    $sat = 0;
    $image = ImageCreateFromString(file_get_contents($image));

    for ($x = 0; $x < ImageSX($image); $x++)
    {
        for ($y = 0; $y < ImageSY($image); $y++)
        {
            $color = ImageColorsForIndex($image, ImageColorAt($image, $x, $y));

            if (is_array($color) === true)
            {
                $sat += Saturation(dechex($color['red']) . dechex($color['green']) . dechex($color['blue']));
            }
        }
    }

    echo ($sat / (ImageSX($image) * ImageSY($image)));
    echo '<hr />';
}

结果如下:

green floor plant:      0.0151028053
black floor plant:      0.0000278867
black and white logo:   0.1245559912
stackoverflow logo:     0.0399864136
google logo:            0.1259357324

仅使用这些示例,如果平均饱和度小于 0.03 或 0.035,我会说图像是地面植物,您可以通过添加额外示例进一步调整它。

于 2009-12-20T17:08:42.620 回答
3

将其外包给人类可能是最容易的。

如果您有预算,请考虑 亚马逊的 Mechanical Turk有关一般描述,请参阅 Wikipedia 。

或者,您可以自己进行外包。编写一个 PHP 脚本来显示您的一张图像,并提示用户将其分类为“徽标”或“平面图”。一旦你在网络服务器上运行了这个,给你的整个办公室发电子邮件,并要求每个人对 20 张图像进行分类作为个人喜好。

更好的是,让它成为一场竞赛——排序最多图像的人将赢得 ipod!

也许最简单的是,邀请你认识的每个人来吃披萨和啤酒,并设置一堆笔记本电脑,让每个人花几分钟时间进行分类。

有一些软件方法可以完成您的任务,但如果它是一次性活动,只有不到几千张图片和至少几百美元的预算,我认为使用人类可能会更容易。

于 2010-01-11T04:42:05.493 回答
2

首先想到的一件事是,平面图的 90 度角线往往比任何普通标志都要多得多。

快速的第一步是在图像上运行Canny 边缘检测,并使用Hough 变换和直线的 rho、Theta 定义对角度进行投票。如果您看到对 rho 求和的 Theta=(0, 90, 180, 270) 非常强的对应关系,您可以将图像分类为平面图。

另一种选择是在 Canny 步骤之后遍历边缘图像,仅计算来自长而连续的线段的选票,从而消除噪声。

于 2009-12-21T19:29:34.907 回答
1

我高度怀疑是否已经存在任何此类工具,并且创建任何准确的工具都不是微不足道的。如果您需要整理一组现有图像(例如,您有一个未排序的目录),那么您也许可以编写一个“足够好”的工具并手动处理故障。如果您需要使用新图像动态执行此操作,则可能是错误的方法。

如果我在前一种情况下尝试这个,我可能会寻找一些可以用作代理的微不足道的不同的东西。平面图通常比徽标大得多(文件大小或图像尺寸)?平面图的颜色是否比徽标少?如果我可以使用一些微不足道的东西获得 75% 的准确率,那可能就是要走的路。

于 2009-12-20T08:44:29.703 回答
1

像这样的东西 - 识别图像中的模式 - 在时间方面往往非常昂贵,非常不可靠并且需要不断更新和修补以匹配新案例。

我可以问你为什么需要这样做吗?在您的网站工作流程中,是否没有一点可以手动确定图像是徽标还是平面图?编写一个让用户在上传时确定哪个是哪个的应用程序不是更容易吗?为什么首先会有一组混合数据?

于 2009-12-20T17:18:59.647 回答
1

尽管认为这是需要人工干预的事情,但您可以做的一件事是检查图像的大小。

一个小的(无论是 MB 还是尺寸)图像都可能是一个标志。

大型(MB 和尺寸)图像可能是平面图。

然而,这只是一种概率测量,绝不是万无一失的。

图像的类型也是一个指标,但不是一个指标。徽标更可能是 JPG、PNG 或 GIF,平面图可能会是 TIFF 或其他无损格式 - 但这并不能保证。

于 2009-12-20T17:39:04.033 回答
1

我首先尝试的一个简单的简单尝试是使用 SVM 来学习从样本中获得的 SIFT 关键点。但在您执行此操作之前,您需要标记一小部分图像,将其指定为 -1(平面图)或 1(徽标)。如果图像具有更多归类为平面图的关键点,则它必须是平面图,如果它具有更多归类为徽标的关键点,则它必须是徽标。在计算机视觉中,这被称为特征袋方法,也是最简单的方法之一。更复杂的方法可能会产生更好的结果,但这是一个好的开始。

于 2009-12-22T07:52:55.993 回答
0

正如其他人所说,这种图像识别通常非常复杂。忘记 PHP。

但是,查看您的示例,我发现一个标准可能工作得很好,如果它确实很容易实现:

通过良好的 OCR 运行图像,看看会弹出什么字符串。如果您发现一堆描述房间或此类功能的词...

我将图像旋转 90 度并再次尝试捕捉垂直标签。

编辑:既然您说您尝试过但它不起作用,那么您可能需要先清理混乱。根据空白对图像进行切片。对每个子图像运行 OCR,以防它在尝试解析行时搞砸了。您可以使用图像编辑器对其进行手动测试以对其进行切片。

于 2009-12-20T19:01:45.833 回答
0

同时使用颜色饱和度图像大小(在以前的答案中分别建议)。使用大量人类分类的图形样本,看看它们如何在二维空间(大小 x 饱和度)中绘制,然后决定在哪里放置边界。边界不必是一条直线,但不要为了使所有点都适合而进行太多曲折,否则您将以牺牲新数据为代价“记忆”样本。最好找到一个适合大多数样本的相对简单的边界,它应该适合大多数数据。

你必须容忍某个错误。对此的万无一失的解决方案是不可能的。如果我选择平面图作为我公司的标志怎么办?(这不是开玩笑,只是碰巧很有趣)

于 2009-12-21T19:30:51.733 回答