我正试图在图像中找到一个白色矩形。矩形大小是固定的。这就是我现在所说的:
BufferedImage bImage = bufferedImage;
int height = bufferedImage.getHeight(); //~1100px
int width = bufferedImage.getWidth(); //~1600px
int neededWidth = width / 2;
int neededHeight = 150;
int x = 0;
int y = 0;
boolean breaker = false;
boolean found = false;
int rgb = 0xFF00FF00;
int fx, fy;
fx = fy = 0;
JavaLogger.log.info("width, height: " + w + ", " + h);
while ((x != (width / 2) || y != (height - neededHeight)) && found == false) {
for (int i = y; i - y < neededHeight + 1; i++) {
for (int j = x; j - x < neededWidth + 1; j++) { //Vareetu buut, ka +1 vajadziigs
//JavaLogger.log.info("x,y: " + j + ", " + i);
long pixel = bImage.getRGB(j, i);
if (pixel != colorWhite && pixel != -1) {
//bImage.setRGB(j, i, rgb);
//JavaLogger.log.info("x,y: " + (j+x) + ", " + (i+y));
breaker = true;
break;
} else {
//bImage.setRGB(j, i, 0xFFFFFF00);
}
//printPixelARGB(pixel);
if ((i - y == neededHeight-10) && j - x == neededWidth-10) {
JavaLogger.log.info("width, height: " + x + ", " + y + "," + j + ", " + i);
fx = j;
fy = i;
found = true;
breaker = true;
break;
}
}
if (breaker) {
breaker = false;
break;
}
}
if (x < (width / 2)) {
x++;
} else {
if (y < (height - neededHeight)) {
y++;
x = 0;
} else {
break;
}
}
//JavaLogger.log.info("width, height: " + x + ", " + y);
}
if (found == true) {
for (int i = y; i < fy; i++) {
for (int j = x; j < fx; j++) {
bImage.setRGB(j, i, 0xFF00FF3F);
}
}
}
JavaLogger.log.info("width, height: " + w + ", " + h);
如果我需要的矩形接近(0;0)
的开头,这可以正常工作,但随着距离越来越远,性能会严重下降。我想知道,如果有什么可以做的吗?
例如,这次搜索耗时近8秒,这是相当多的。 我在想,这可以更有效地完成。也许有些斑点发现?阅读它,但我不知道如何应用它。
此外,我是Java和图像处理的新手,所以感谢任何帮助。
答案 0 :(得分:1)
这非常粗糙,但成功找到了图像中的所有白色像素,可以进行更多检查以确保它符合您想要的尺寸,一切都在那里,但基础知识就在那里。
PS:我没有测试你的图像。 r
和this.rc
是图片尺寸,p
和this.px
是内部矩形尺寸
public static void main(String[] args) {
JFrame frame = new JFrame();
final int r = 100;
final int p = 10;
NewJPanel pan = new NewJPanel(r, p, new A() {
@Override
public void doImage(BufferedImage i) {
int o = 0;
for (int j = 0; j < i.getWidth() - p; j++) {
for (int k = 0; k < i.getHeight() - p; k++) {
PixelGrabber pix2 = new PixelGrabber(
i, j, k, p, p, false);
try {
pix2.grabPixels();
} catch (InterruptedException ex) {}
int pixelColor = pix2.getColorModel()
.getRGB(pix2.getPixels());
Color c = new Color(pixelColor);
if (c.equals(Color.WHITE)) {
System.out.println("Found at : x:" + j + ",y:" + k);
}
}
}
}
});
frame.getContentPane().add(pan);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private interface A {
void doImage(BufferedImage i);
}
private static class NewJPanel extends JPanel {
private static final long serialVersionUID = -5348356640373105209L;
private BufferedImage image = null;
private int px;
private int rc;
private A a;
public NewJPanel(int r, int p, A a) {
this.px = p;
this.rc = r;
this.a = a;
}
public BufferedImage getImage() {
return image;
}
@Override public void paint(Graphics g) {
super.paint(g);
image = new BufferedImage(this.rc, this.rc,
BufferedImage.TYPE_INT_ARGB);
java.awt.Graphics2D g2 = image.createGraphics();
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, this.rc, this.rc);
g2.setColor(Color.WHITE);
g2.fillRect(
new Random().nextInt(this.rc - this.px),
new Random().nextInt(this.rc - this.px),
this.px, this.px);
g.drawImage(image, this.rc, this.rc, this);
this.a.doImage(this.image);
}
}
答案 1 :(得分:0)
我不是专家,但我认为代码不是问题 - 您需要更改算法。我将首先在2d平面上递归搜索单个白色像素,如:
findWhitePixel(正方形){ 看看'square'中间的像素 - 如果是白色则返回它,否则: findWhitePixel('square'的右上角四分之一) findWhitePixel('square'的左上角) findWhitePixel('square'的右下角四分之一) findWhitePixel('square'的左下角) }
找到白色像素后,尝试向上,向下,向左和向右移动,以找到形状上的边框。如果它是一个给定的只有矩形 - 你做完了。如果可能有其他形状(三角形,圆形等),你需要在这里进行一些验证。
答案 2 :(得分:0)
你所要求的可以通过称为“侵蚀”的操作来解决。侵蚀将每个像素替换为该位置(左上角)所请求大小的矩形中最暗的所有像素。在这里,最黑暗意味着非白色取代白色。
侵蚀的输出是W-1列和H-1行的图像。其中的任何白色像素都对应于解决方案。
在矩形形状的幸运案例中,侵蚀是一种可分离的操作。这意味着您可以首先使用水平线段形状进行侵蚀,然后在第一次侵蚀的输出上使用垂直线段形状进行侵蚀。对于W x H restangle大小,这将W * H替换为W + H,这是一个显着的节省。
在二进制图像(非白色或白色)的幸运情况下,可以非常有效地完成段的侵蚀:在每一行中独立地找到所有连续的白色像素,并将W-1转到最右边非白色的。对所有列执行相同操作,将白色运行缩短为H-1像素。
示例:找到所有3x2矩形:
####....####
##.....#..##
#..######...
.....###....
3x1侵蚀后:
####..####
##...#####
#########.
...#####..
1x2侵蚀后:
####.#####
##########
#########.
此算法每个像素占用恒定时间(无论矩形大小)。正确实施,应该花费一些毫秒。