Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сравнение двух BufferedImage, нужна помощь  
:(
    Опции темы
oleg1dorozhko
Дата 19.7.2014, 18:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2014

Репутация: нет
Всего: нет



Сейчас код для сравнения такой:

Код

package context;


import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

import cd.CompareDemo;
import engine.ScriptProcessor;

import test1.TestApp;


import app.AppConst;
import app.AppLogger;


public class ImageContextSearcher 
{
    
    public int DIFFERENCE = 20;
    public float probability = 0.9f;
    
    
    
    
        
    public ImageContextSearcher( )
    {
        
    }
    
    
    
    public boolean equal(int n1, int n2)
    {
        int dif=0;
        if (n1>n2) dif = n1-n2;
        else if (n2>n1) dif = n2-n1;
         
        return (dif < DIFFERENCE );
    }

    
    private boolean isEqual(int[] rgb, int[] pixel) 
    {
        if(equal(rgb[0], pixel[0]) && equal(rgb[1], pixel[1]) && equal(rgb[2], pixel[2]))  return true;
        
        return false;
    }
    
    public boolean cmpImages(BufferedImage scan,    BufferedImage part) 
    {
    
        for(int n=0;n<scan.getWidth();n++)
        {
            for(int m=0;m<scan.getHeight();m++)
            {
                int[] rgb = scan.getRaster().getPixel(n, m, new int[3]);
                int[] pixel = part.getRaster().getPixel(n, m,  new int[3]);
                
                if(isEqual(rgb, pixel)) continue;
                    
                return false;
            }
        }
        
        return true;
    }

    
    
    

}



Но сравнение идет попиксельно. Но что если точки с одним и тем же цветом находятся на некотором удалении - сдвинулась точка скана при рендере. Результат будет ложный, хотя визуально картинки одинаковые.
И даже более реалистичный вариант - сдвинуто причем по разному некоторое число точек.
Как сравнить картинки в таком случае?
PrintScreen векторной графики приводит к таким казусам. А сравнить нужно.

Кто подскажет что делать?



PM MAIL   Вверх
oleg1dorozhko
Дата 19.7.2014, 20:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2014

Репутация: нет
Всего: нет



Пока придумал вот что:

1. Считаем количества каждого цвета в скане и образце
2. Составляем графики частот в скане и образце
3. Сравниваем эти графики

Осталось реализовать в коде, так чтобы это работало, и работало не просто быстро, а очень быстро
PM MAIL   Вверх
Stolzen
Дата 19.7.2014, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1041
Регистрация: 17.10.2005

Репутация: 3
Всего: 48



Если графики частот будете считать не преобразованием Фурье, а какими-нибудь вейвлетами, то должно быть быстрее. По крайней мере на лабах в университете именно так и было smile Правда я подробностей уже не помню, к сожалению


--------------------
datatalks.ru - анализ данных, статистика, машинное обучение
PM MAIL WWW   Вверх
oleg1dorozhko
Дата 19.7.2014, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2014

Репутация: нет
Всего: нет



Пришла в голову идея использовать трехмерную матрицу вида m[R,G,B], значение в каждой ячейке которой есть количество цвета

Сейчас попробую реализовать, посмотрим, что получится.

Это сообщение отредактировал(а) oleg1dorozhko - 19.7.2014, 22:19
PM MAIL   Вверх
oleg1dorozhko
Дата 20.7.2014, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2014

Репутация: нет
Всего: нет



Код

package comparator;

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

public class RGBComparator 
{

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        
        try
        {
        
            log("Start");
            long time1 = System.currentTimeMillis();
            
            BufferedImage img1 = ImageIO.read(new File("res/guild.png"));
            
            BufferedImage img2 = ImageIO.read(new File("res/scan1.png"));
            
            int[][][] rgb = new int[256][256][256];
            
            int w1 = img1.getWidth();
            int h1 = img1.getHeight();
            
            for(int i=0;i<w1; i++)
            {
                for(int j=0; j<h1; j++)
                {
                    int[] rgb1 = img1.getRaster().getPixel(i, j, new int[3]);
                    
                    rgb[rgb1[0]][rgb1[1]][rgb1[2]] ++;
                    
                    
                }
            }
            
            
            
            
            
            int w2 = img2.getWidth();
            int h2 = img2.getHeight();
            
            for(int x=0; x<(w2-w1)+1;x++)
            {
                for(int y=0;y<(h2-h1)+1;y++)
                {
                    
                    //log("...");
                    
                    int errors = 0;
                    
                    int[][][] c_rgb = copyRGB(rgb);
                    
                    for(int i=0;i<w1; i++)
                    {
                        for(int j=0; j<h1; j++)
                        {
                            
                                int[] rgb2 = img2.getRaster().getPixel((x+i), (y+j), new int[3]);
                                
                                int v = c_rgb[rgb2[0]][rgb2[1]][rgb2[2]];
                                
                                if( v == 0) { errors++; continue; }
                                
                                c_rgb[rgb2[0]][rgb2[1]][rgb2[2]] --;
                        
                        }
                    }
                    
                    int zcounter=0;
                    int pcounter=0;
                    int mcounter=0;
                    
                    for(int r=0;r<256;r++)
                    {
                        for(int g=0;g<256;g++)
                        {
                            for(int b=0;b<256;b++)
                            {
                                if(c_rgb[r][g][b]>0) pcounter++;
                                else if(c_rgb[r][g][b]<0) mcounter++;
                                else zcounter++;
                            }
                        }
                    }
                    
                    
                    
                    if(pcounter < 10 && mcounter < 10)
                    {
                        log("For ["+x+","+y+"]");
                        log("errors= "+errors);
                        log("pcounter= "+pcounter);
                        log("zcounter= "+zcounter);
                        log("mcounter= "+mcounter);
                        
                    }
                    
                    
                    
                }
            }
            
            long time2 = System.currentTimeMillis();
            log("Finish");
            log("ET(ms)= "+(time2-time1));
        
        
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }

    private static int[][][] copyRGB(int[][][] rgb) 
    {
        int[][][] res = new int[256][256][256];
    
        for(int r=0;r<256;r++)
        {
            for(int g=0;g<256;g++)
            {
                for(int b=0;b<256;b++)
                {
                    res[r][g][b] = rgb[r][g][b];
                }
            }
        }
        
        return res;
    }

    private static void log(String s) 
    {
        System.out.println(s);
        
    }

}


Вот рабочий код. Но работает очень медленно.
Что тут можно оптимизировать для ускорения работы?

Добавлено через 1 минуту и 55 секунд
Скан может быть 1368 на 768 точек

Образец для сравнения 20 на 20 точек
PM MAIL   Вверх
oleg1dorozhko
Дата 20.7.2014, 02:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2014

Репутация: нет
Всего: нет



Вот что получилось в итоге:

Код

package comparator;

import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class RGBComparator2 
{

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        
        try
        {
        
            //testColors();
            
            log("Start");
            long time1 = System.currentTimeMillis();
            
            BufferedImage img1 = ImageIO.read(new File("res/guild.png"));
            BufferedImage img2  = ImageIO.read(new File("res/scan.png"));
            
            compareImages(img1, img2);
            
            long time2 = System.currentTimeMillis();
            log("Finish");
            log("ET(ms)= "+(time2-time1));
        
        
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }

    private static void testColors() 
    {
        Color c = Color.WHITE;
        log(""+c.getRGB());
        int rgb_rgb=c.getRGB();
        int r = ((rgb_rgb >> 0 * 8) & 255);
        int g = ((rgb_rgb >> 1 * 8) & 255);
        int b = ((rgb_rgb >> 2 * 8) & 255);
        Color c1 = new Color(r,g,b);
        log("r="+r);
        log("g="+g);
        log("b="+b);
        log(""+c1.getRGB());
    }

    
    
    private static void compareImages(BufferedImage img1, BufferedImage img2) throws IOException 
    {
        
         
        
        int[] rgb = new int[256*256*256];
        
        for(int i=0;i<256*256*256;i++) rgb[i]=0;
                
        
        int w1 = img1.getWidth();
        int h1 = img1.getHeight();
        
        for(int i=0;i<w1; i++)
        {
            for(int j=0; j<h1; j++)
            {
                int[] rgb1 = img1.getRaster().getPixel(i, j, new int[3]);
                
                
                rgb[256*256*rgb1[0] + 256*rgb1[1] + rgb1[2]] ++;
                
                
            }
        }
        
        
        
        
        
        int w2 = img2.getWidth();
        int h2 = img2.getHeight();
        
         
        int max_cmp = 0;
        Point min_point = null;
        
        for(int x=0; x<(w2-w1)+1;x++)
        {
            for(int y=0;y<(h2-h1)+1;y++)
            {
                
                //log("...");
                
                 
                int zcounter=0;
                
                for(int i=0;i<w1; i++)
                {
                    for(int j=0; j<h1; j++)
                    {
                        
                            int[] rgb2 = img2.getRaster().getPixel((x+i), (y+j), new int[3]);
                            
                            
                            if( rgb[256*256*rgb2[0] + 256*rgb2[1] + rgb2[2]] != 0) zcounter++;
                            
                            
                    
                    }
                }
            
            

                
                
                
                
                if(max_cmp < zcounter)
                {
                        max_cmp = zcounter;
                        min_point = new Point(x,y);
                        
                    
                }
                
                
                
                
                
            }
        }
        
        
        if(min_point != null)
        {
            log("Found at: ["+min_point.x+","+min_point.y+"] with max_cmp: "+max_cmp);
        }
        
    }

    
    private static void log(String s) 
    {
        System.out.println(s);
        
    }
    
    

}


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   jk1
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема »


 




[ Время генерации скрипта: 0.0477 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.