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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Shape из изображения, Сложная форма 
:(
    Опции темы
Platon
Дата 6.5.2008, 06:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Здравствуйте, уважаемые.

Меня интересует вопрос. Как можно создать Shape по растровому образу. К примеру, у нас есть черно-белое изображение, на котором черным цветом изображено что-то, к примеру пара-тройка рядомстоящих коров. Хочется 1-м махом определить их форму в Shape.
PM MAIL ICQ   Вверх
Platon
Дата 6.5.2008, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Не хочет ли молчащая аудитория сказать, что я должен сделать это сам?
PM MAIL ICQ   Вверх
AlexeyVorotnikov
Дата 7.5.2008, 07:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 18.6.2007
Где: Москва

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



ИМХО, распознавание образов -- задача не тривиальная...


--------------------
RTFM!
Три источника и три составные части Java: The Java Language Specification, Java Platform API Specification, The Java Virtual Machine Specification
PM MAIL   Вверх
Platon
Дата 7.5.2008, 08:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Я бы так не сказал. Ведь к примеру есть такой механизм, который делает прозрачным цветом малиновый фон, в итоге получается сложная форма. Нетривиальной задача была бы если бы нужно было распознать образ из многоцветного и с оттенками изображения, задача тут намного проще, из ч-б изображения как бы обвернуть все черные островки. Слышал про задачу береговой линии, но что-то найти в интернете не могу.
PM MAIL ICQ   Вверх
Platon
Дата 7.5.2008, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Код

package ru.vingrad.platon.awt;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

// TODO: не работает с бубликом
public class RasterMaskShapeBuilder {

    public static final int INCLUDE = 1;
    public static final int EXCLUDE = 2;

    private int type;
    private int color;
    private int w;
    private int h;

    private static final int[][] MOVES = new int[][] {
            {1, 0},
            {1, -1},
            {0, -1},
            {-1, -1},
            {-1, 0},
            {-1, 1},
            {0, 1},
            {1, 1}
    };

    private static final int HOLE_COLOR = -1;

    public Shape buildShape(BufferedImage image, Color color, int type) {
        if (! (type == INCLUDE || type == EXCLUDE)) throw new IllegalArgumentException("Type must be or INCLUDE or EXCLUDE");
        this.color = color.getRGB() & 0xFFFFFF;
        this.type = type;
        w = image.getWidth();
        h = image.getHeight();
        // TODO: надо нормально выхватить массив, пока не работает
        int[] raster = image.getRaster().getPixels(0, 0, w, h, new int[w*h]);

        GeneralPath shape = new GeneralPath();
        Point point = new Point();
        for (int i = 0; i < h; i++) {
            int off = i*w;
            point.y = i;
            for (int j = 0; j < w; j++) {
                point.x = j;
                // TODO: пока flood feel, потому что не работает shape.contains(Point2D)
                if (isShapePart(raster[off + j])) {
                    shape.append(builPart(raster, j, i), false);
                    // хитрый флад фил, связано с реализацией.
                    // Если пустить наводнение с точки (i, j), то может закрасится еще недобавленная форма
                    // пример шахматная доска {{бчб}{чбч}} будет распознана форма {{_ч_}{__ч}}
                    // а при наводнееии будет удалена форма {{_ч_}{ч_ч}}
                    raster[off + j] = HOLE_COLOR;
                    int direction = 0;
                    for (int i1 = 0; i1 < MOVES.length; i1++) {
                        final int[] move = MOVES[i1];
                        if (isShapePart(getColor(raster, j + move[0], i + move[1]))) {
                            direction = i1;
                            break;
                        }
                    }
                    floodFeel(raster, i + MOVES[direction][1], j + MOVES[direction][0]);
                }
            }
        }
        return shape;
    }

    private void floodFeel(int[] raster, int i, int j) {
        floodFeel(raster, i, j, 0);
    }

    // TODO: флад фил ограничен, радиус охвата 1000 пикселов, остается опасность переполнения стека
    private void floodFeel(int[] raster, int i, int j, int depth) {
        if (depth < 1000 && i >= 0 && i < h && j >= 0 && j < w && isShapePart(raster[i*w + j])) {
            raster[i*w + j] = HOLE_COLOR;
            for (int[] moves : MOVES)
                floodFeel(raster, i + moves[1], j + moves[0], depth + 1);
        }
    }

    private Shape builPart(int[] raster, int x, int y) {
        Polygon p = new Polygon();
        p.addPoint(x, y);
        int direction = 0;
        int cx = x, cy = y;
        do {
            int newDirection = turnLeft(direction, 2);
            int endDirection = turnLeft(direction, 4);
            while (endDirection != newDirection && !isShapePart(getColor(raster, cx + MOVES[newDirection][0], cy + MOVES[newDirection][1]))) {
                newDirection = turnRight(newDirection);
            }
            // Случай, когда у нас на входе 1 точка, мы ее уже поставили, и пора бы нам выходить
            // TODO: придумать что-нибудь умнее
            if (cx == x && cy == y && newDirection == endDirection)
                break;
            if (newDirection != direction && !(cx == x && cy == y))
                p.addPoint(cx, cy);
            cx += MOVES[newDirection][0];
            cy += MOVES[newDirection][1];
            direction = newDirection;
        } while (!(cx == x && cy == y));
        return p;
    }

    private int getColor(int[] raster, int x, int y) {
        return (x >= 0 && x < w && y >= 0 && y < h)? raster[y*w + x] : HOLE_COLOR;
    }

    private boolean isShapePart(int i) {
        return i == color && type == INCLUDE;
    }

    private static int turnLeft(int direction) {
        return turnLeft(direction, 1);
    }

    private static int turnLeft(int direction, int times) {
        return (direction + times) % MOVES.length;
    }

    private static int turnRight(int direction, int times) {
        return (MOVES.length + direction - times) % MOVES.length;
    }

    private static int turnRight(int direction) {
        return turnRight(direction, 1);
    }

    public static void main(String[] args) throws IOException {
        JFrame f = new JFrame();
        final Shape s = new RasterMaskShapeBuilder().buildShape(ImageIO.read(new File("test.gif")), Color.BLACK, INCLUDE);
        JComponent p = new JComponent() {
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D)g;
                g2.fill(s);
            }
        };
        p.setSize(400, 400);
        f.getContentPane().add(p);
        f.pack();
        f.setLocationByPlatform(false);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}


Добавлено @ 13:26
Нетривиального ничего нет, просто идет обход по контуру. Прошу форумян помочь, отмеченны некоторые ТУДУшки, особенно необходима помощь с массивом пикселов, что-то не выбирается путево :(

Это сообщение отредактировал(а) Platon - 7.5.2008, 14:16

Присоединённый файл ( Кол-во скачиваний: 18 )
Присоединённый файл  test.gif 1,41 Kb
PM MAIL ICQ   Вверх
w1nd
Дата 10.5.2008, 02:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вертилятор
***


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

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



Есть простой, хоть и относительно медленный способ:

 - создать Area из прямоугольника по размеру изображения;
 - построчно сканировать изображение и добавлять в Area нужные отрезки (для всех примитивов в java2d есть реализации shape).



Это сообщение отредактировал(а) w1nd - 10.5.2008, 02:18


--------------------
user posted imageuser posted image
PM MAIL ICQ   Вверх
willu
Дата 23.9.2008, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Может ето не по теме, но меня интересует такое. Есть ренгеновский снимок. Белый цвет - ето здоровая кость, а чёрный - перелом.Какой алгоритм нужен для опредиления чёрного цвета и его одтенка? Нужно просто вывести график одтенко, например в СиШарп.
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.1212 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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