Java 如何基于纯色区域和重复图案对图像进行分类
我有一个简单的图像分类问题。我正在编写一个拼图应用程序,需要将图像分类到难度级别(例如,简单、中等、困难) 我想为这个分类开发一个简单的算法,难度基于像大的纯色区域和图像上重复的图案这样的因素。这样的分类可以在下面的网站上看到。 我想在没有太多人为干预的情况下自动进行分类。这可能吗?最好的方法是什么。(不担心性能,简单就好,不需要太高的准确性) 更多关于难度的细节和例子 编辑:我想提出一个简单的算法来粗略地对图像进行分类或评分这是我的“简单算法”版本。这是基于碎片之间的成对比较,但在直径约为碎片大小的1/10的情况下进行模糊处理。所以是的,你必须先设置水平和垂直方向上的工件数量。所有测试中使用的默认数量为40*25=1000件。工作复杂性(或者难度,如果你允许我在这里使用这个词的话)这里是各部分之间的平均相似性。我知道这是一种奇怪的测量方法,但是你拥有的相似的碎片越多,谜题就越难。对吧?Java 如何基于纯色区域和重复图案对图像进行分类,java,image-processing,Java,Image Processing,我有一个简单的图像分类问题。我正在编写一个拼图应用程序,需要将图像分类到难度级别(例如,简单、中等、困难) 我想为这个分类开发一个简单的算法,难度基于像大的纯色区域和图像上重复的图案这样的因素。这样的分类可以在下面的网站上看到。 我想在没有太多人为干预的情况下自动进行分类。这可能吗?最好的方法是什么。(不担心性能,简单就好,不需要太高的准确性) 更多关于难度的细节和例子 编辑:我想提出一个简单的算法来粗略地对图像进行分类或评分这是我的“简单算法”版本。这是基于碎片之间的成对比较,但在直径约为碎
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);
}
}
PS:这种情况下的复杂性是工作的难度,而不是图片上数据的复杂性
PPS:算法非常不优化。这只是概念上的证明。投票结束的范围太广。Wikipedia和Google是你的人,而不是Stack Overflow你在寻找什么样的答案?看起来很模糊。纯色区域的问题应该不会太难解决,例如用于泛光填充(因为性能并不重要)。至于模式识别,这有点困难,但应该可以使用OpenCVP解决,谢谢您的输入。我现在已经更新了问题。我想提出一个算法来大致分类图像。我能用直方图吗?或者类似的东西,这样就可以给分数了。然后根据分数确定愤怒的难度。@pats为什么不试试呢?直方图应该很容易实现,它可能只需要几行Matlab。如果结果很好,请用Java实现,否则请尝试另一种方法。你不是在问一个计划性的问题,你是在要求为你做整个研究工作,非常接近我所追求的。干得真不错。谢谢我注意到的唯一问题是模式(例如)给出了0.5的值。根据范围1-高难度和0是最低的不是吗?@pats,嗯,很有趣。与其他情况相比,0.5相当低。也许有可能添加(结合我的建议)另一种类型的分析,重点是水平和垂直方向上不同颜色的相邻像素对的频率。。。
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