如何基于纯色区域和重复图案对图像进行分类

时间:2015-10-14 00:13:47

标签: java image-processing

我有一个简单的图像分类问题。我正在编写一个拼图应用程序,需要将图像分类到难度级别(例如,简单,中等,难度)。

我想为这种分类开发一种简单的算法,难度基于像大的纯色区域和图像上的重复图案等因素。这种分类可以在以下网站上看到。 http://www.whitemountainpuzzles.com/Shop-by-Difficulty/departments/136/ http://www.seriouspuzzles.com/sjigsbeg.asp

我想在没有太多人为干预的情况下自动化这种分类。这是可能的,并且最好的方法是什么。 (不担心性能,简单就好,不需要巨大的准确性)

有关难度http://www.ulillillia.us/tipsntricks/jigsawpuzzledifficultytrick.shtml

的更多详细信息和示例

编辑:我想提出一个简单的算法来大致分类图像或给出分数

1 个答案:

答案 0 :(得分:1)

这是我的“简单算法”版本。它基于碎片之间的成对比较,但在模糊后直径约为1/10的块尺寸。所以是的,你必须首先在水平和垂直方向上设置件数。所有测试中使用的默认编号为40 * 25 = 1000件。工作复杂性(或者如果你让我在这种情况下使用这样的单词那么困难)这里是作品之间的平均相似性。我知道这是一个奇怪的措施,但是你越难相似,你就会越难。正确?

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.imageio.ImageIO;

public class JigsawComplexityTest {
    private static final int defaultHorizontalCount = 40;
    private static final int defaultVerticalCount = 25;

    public static void main(String[] args) throws Exception {
        String test1 = "http://www.ulillillia.us/images/mgscreen.png";
        String test2 = "http://www.ulillillia.us/images/easyjigsawpuzzleimage.png";
        String test3 = "http://www.ulillillia.us/images/hardjigsawpuzzleimage.jpg";
        String test4 = "http://students.cec.wustl.edu/~billchang/cse559/project2/result9.jpg";
        String mostlyGreen = "http://keera.co.uk/blog/wp-content/uploads/2014/08/Screenshot_2014-07-27-22-26-23.png";
        String grass = "http://p1.pichost.me/i/75/2000933.jpg";
        String flowerFields = "http://p1.pichost.me/i/14/1371715.jpg";
        String people = "http://captital-connection.com/wp-content/uploads/2014/10/capitalconnectionpeople.jpg";
        String nature = "http://static.hdw.eweb4.com/media/wallpapers_1920x1200/nature/1/4/pond-between-the-flowers-nature-hd-wallpaper-1920x1200-32983.jpg";
        String puzzle1 = "http://jigsawpuzzlesforadults.com/wp-content/uploads/2013/11/5000-Piece-Jigsaw-Puzzle-Needle-Mountains.png";
        String puzzle2 = "http://jigsawpuzzlesforadults.com/wp-content/uploads/2013/11/18000-Piece-Jigsaw-Puzzle-Paraadise-Sunset.png";
        String puzzle3 = "http://jigsawpuzzlesforadults.com/wp-content/uploads/2013/11/5000-Piece-jigsaw-puzzle-PuzzleRavensburger-Views-of-Modern-Rome-.png";
        String puzzle4 = "http://jigsawpuzzlesforadults.com/wp-content/uploads/2013/11/5000-Piece-Puzzle-James-Rizzi_-City-.png";
        System.out.println("Test1: " + getComplexity(test1));
        System.out.println("Test2: " + getComplexity(test2));
        System.out.println("Test3: " + getComplexity(test3));
        System.out.println("Test4: " + getComplexity(test4));
        System.out.println("Mostrly green: " + getComplexity(mostlyGreen));
        System.out.println("Grass: " + getComplexity(grass));
        System.out.println("Flower fields: " + getComplexity(flowerFields));
        System.out.println("Nature: " + getComplexity(nature));
        System.out.println("People: " + getComplexity(people));
        System.out.println("Puzzle1: " + getComplexity(puzzle1));
        System.out.println("Puzzle2: " + getComplexity(puzzle2));
        System.out.println("Puzzle3: " + getComplexity(puzzle3));
        System.out.println("Puzzle4: " + getComplexity(puzzle4));
    }

    public static double getComplexity(String url) throws IOException {
        InputStream is = new URL(url).openStream();
        try {
            BufferedImage img = ImageIO.read(is);
            return getComplexity(img, defaultHorizontalCount, defaultVerticalCount);
        } finally {
            is.close();
        }
    }

    public static double getComplexity(BufferedImage img, int xCount, int yCount) {
        int w = img.getWidth();
        int h = img.getHeight();
        Color[][] pixels = new Color[h][w];
        for (int y = 0; y < h; y++)
            for (int x = 0; x < w; x++)
                pixels[y][x] = new Color(img.getRGB(x, y));
        int pw = w / xCount;
        int ph = h / yCount;
        pixels = blur(pixels, pw / 5, ph / 5);
        double sumCompl = 0;
        int denominator = 0;
        for (int i = 0; i < xCount; i++)
            for (int j = 0; j < yCount; j++)
                for (int n = i; n < xCount; n++)
                    for (int m = j; m < yCount; m++) {
                        if (i == n && j == m)
                            continue;
                        sumCompl += compareSubimages(pixels, i * pw, j * ph, n * pw, m * ph, pw, ph);
                        denominator++;
                    }
        return sumCompl / denominator;
    }

    private static Color[][] blur(Color[][] input, int dx, int dy) {
        if (dx < 2)
            dx = 2;
        if (dy < 2)
            dy = 2;
        Color[][] ret = new Color[input.length][input[0].length];
        for (int y = 0; y < input.length; y++)
            for (int x = 0; x < input[y].length; x++) {
                int r = 0;
                int g = 0;
                int b = 0;
                int denominator = 0;
                for (int i = -dx; i <= dx; i++) {
                    if (x + i < 0 || x + i >= input[y].length)
                        continue;
                    for (int j = -dy; j <= dy; j++) {
                        if (y + j < 0 || y + j >= input.length)
                            continue;
                        Color c = input[y + j][x + i];
                        r += c.getRed();
                        g += c.getGreen();
                        b += c.getBlue();
                        denominator++;
                    }
                }
                ret[y][x] = new Color(r / denominator, g / denominator, b / denominator);
            }
        return ret;
    }

    private static double compareSubimages(Color[][] pixels, int x1, int y1, 
            int x2, int y2, int pw, int ph) {
        double ret = 0;
        for (int i = 0; i < pw; i++)
            for (int j = 0; j < ph; j++) {
                Color c1 = pixels[y1 + j][x1 + i];
                Color c2 = pixels[y2 + j][x2 + i];
                ret += Math.max(Math.max(Math.abs(c1.getRed() - c2.getRed()) / 255.0, 
                        Math.abs(c1.getGreen() - c2.getGreen()) / 255.0),
                        Math.abs(c1.getBlue() - c2.getBlue()) / 255.0);
            }
        return 1.0 - ret / (pw * ph);
    }
}

这是输出:

Test1: 0.6769529450450067
Test2: 0.28125444354771767
Test3: 0.9002461442832157
Test4: 0.9406619849710389
Mostrly green: 0.8951158950955296
Grass: 0.8590196334404887
Flower fields: 0.7202705256209023
Nature: 0.6829507611296955
People: 0.5517856536390812
Puzzle1: 0.49445824310139086
Puzzle2: 0.6918959038799397
Puzzle3: 0.7519219343473392
Puzzle4: 0.7367090900702122

PS:在这种情况下,复杂性是工作难度,而不是图片数据的复杂性。

PPS:该算法非常不优化。这只是概念的证明。