Существует ли правильный алгоритм определения цвета фона фигуры?

Для колледжа нам дали задание, где, учитывая изображение, мы должны определить "цифры», их цвет и количествопиксельные-групп» внутри них. Позволь мне объяснить:

На изображении выше есть одинфигура (на изображении может быть несколько фигур, но давайте пока об этом забудем).

Цвет фона холста - пиксель в 0,0 (в данном случае, желтый)Цвет границы рисунка - черный (это может быть любой цвет, кроме холста) фоновый цвет).Фигураs цвет фона белый (он также может быть таким же, как холст фоновый цвет).Фигура может иметь только один цвет фона.На рисунке две группы пикселей. Один - это пул синих пикселей, а другой - пул красного с зеленым внутри. Как вы можете видеть, это нене имеет значения цвет группы пикселейs пикселей (это просто отличается от цифры "цвет фона). Важно то, что ониповторно в контакте (даже по диагонали). Таким образом, несмотря на наличие двух разных цветов, такая группа в любом случае считается только одной.Как видите, граница может быть нерегулярной, как вы хотите. Он имеет только один цвет.Известно, что группа пикселей не будет касаться границы.Мне сказали, что группа пикселейЦвета могут быть любыми, кроме фигурыцвет фона. Я предполагаю, что тогда это может быть таким же, как на рисункеЦвет границы s (черный).

Нам был дан класс, способный снимать изображения и преобразовывать их в матрицу (каждый элемент представляет собой целое число, представляющее цвет пикселя).

И этосидеть. Я'Я делаю это с Java.

Что я сделал так далеко

Итерация по каждому пикселю в матрицеЕсли я найду пиксель, отличный от цвета фона, я предположу, что он принадлежит границе рисунка. Я назову этот пиксельinitialPixel впредь.Обратите внимание, чтоinitialPixel на изображении, которое я указал, изображен черный пиксель в верхнем левом углу рисунка. Я специально сделал резкий разрез, чтобы проиллюстрировать это.Моя задача сейчас - найти цвет фона фигуры (в данном случае белый).

Но я'У меня довольно много проблем, чтобы найти такой цвет фона (белый). Это самый близкий метод, который я сделал, который работал в некоторых случаях - но не с этим изображением:

Так как я знаю цвет границы, я мог бы найти первый другой цвет, которыйюг изinitialPixel, Звучит как хорошая идея - иногда это работает, но не будет работать с предоставленным изображением: в этом случае он вернется желтым, посколькуinitialPixel довольно далеко от фигурыс содержанием.

Предполагая, что я нашел фигуруs цвет фона (белый), моей следующей задачей было бы понять, что на рисунке существуют две группы пикселей. Этот кажется проще:

Так как теперь я знаю фигуруs цвет фона (белый), я могу попытаться перебрать каждый пиксель на рисунке и, если найду один, который не принадлежит границе и не является частью рисунка 'С фоном, я уже могу сказать, что есть одна группа пикселей. Я могу начать рекурсивную функцию, чтобы найти все пиксели, связанные с такой группой и "флаг" их так, чтобы в будущих итерациях я мог полностью игнорировать такие пиксели.

ЧТО МНЕ НУЖНО

Да, моя проблема в том, как найти фигуруs цвет фона (имейте в виду, что он может быть таким же, как все изображениеs цвет фона - на данный момент это желтый, но может быть и белый цвет) на основе того, что я описал ранее.

Я немне не нужен код - яЯ просто не могу придумать правильный алгоритм для такого. Тот факт, что на границе могут быть такие странные нерегулярные линии, убивает меня.

Или даже лучше: я делал все это неправильно? Может быть, я не должентак много на этом сфокусировалиinitialPixel совсем. Может быть, сработал бы другой метод? Есть ли какие-либо документы / примеры на подобные темы? Я понимаю, что есть много исследований "компьютерное зрение" и такие, но я могуне могу найти много об этой конкретной проблеме.

НЕКОТОРЫЙ КОД

Моя функция для извлечения вектора со всеми фигурами: * Примечание:Figure это просто класс, который содержит некоторые значения, такие как цвет фона и количество элементов.

public Figure[] getFiguresFromImage(Image image) {
    Figure[] tempFigures = new Figure[100];
    int numberOfFigures = 0;
    matrixOfImage = image.getMatrix();
    int imageBackgroundColor = matrixOfImage[0][0];
    int pixel = 0;

    for (int y = 0; y < matrixOfImage.length; ++y) {
        for (int x = 0; x < matrixOfImage[0].length; ++x) {
            pixel = matrixOfImage[y][x];
            if (!exploredPixels[y][x]) {
                // This pixel has not been evaluated yet
                if (pixel != imageBackgroundColor ) {
                    // This pixel is different than the background color
                    // Since it is a new pixel, I assume it is the initial pixel of a new figure
                    // Get the figure based on the initial pixel found
                    tempFigures[numberOfFigures] = retrieveFigure(y,x);
                    ++numberOfFigures;
                }
            }
        }   
    }

    // ** Do some work here after getting my figures **

    return null;
}

Тогда, понятно, функцияretrieveFigure(y,x) это то, что я не могу сделать.

Заметки:

В учебных целях я не должен использовать какие-либо внешние библиотеки.
 Andrew Thompson21 окт. 2012 г., 08:06
Увидетьэтот ответ который сталэтот вопрос для одного подхода к поиску областей, где происходит цвет.
 DarthVader21 окт. 2012 г., 08:03
Как определить фон изображения и рассказать своей программе?
 DarthVader21 окт. 2012 г., 08:04
на твоей картинке? белый фон или желтый? я даже не могу сказать это. даже черный может быть фоном.
 Voldemort21 окт. 2012 г., 08:06
@DarthVader: Ах! Я'мне жаль Цвет фона холста - пиксель при 0,0. И рисунок не коснется границы холста.

Ответы на вопрос(2)

Попробуйте этот код:

import java.util.Scanner;
import java.awt.image.BufferedImage;
import java.io.*;

import javax.imageio.ImageIO;

class Analyzer{
    private int pixdata[][];
    private int rgbdata[][];
    private BufferedImage image;
    int background_color;
    int border_color;
    int imagebg_color;
    private void populateRGB(){
        rgbdata = new int[image.getWidth()][image.getHeight()];
        for(int i = 0; i < image.getWidth(); i++){
            for(int j = 0; j < image.getHeight(); j++){
                rgbdata[i][j] = image.getRGB(i, j);
            }
        }
        int howmanydone = 0;
        int prevcolor,newcolor;
        prevcolor = rgbdata[0][0];

        /*
        for(int i = 0; i < image.getWidth(); i++){
           for(int j = 0; j < image.getHeight(); j++){
              System.out.print(rgbdata[i][j]);
           }
           System.out.println("");
        }*/
        for(int i = 0; i < image.getWidth(); i++){
            for(int j = 0; j < image.getHeight(); j++){
                newcolor = rgbdata[i][j];
                if((howmanydone == 0) && (newcolor != prevcolor)){
                    background_color = prevcolor;
                    border_color = newcolor;
                    prevcolor = newcolor;
                    howmanydone = 1;
                }
                if((newcolor != prevcolor) && (howmanydone == 1)){
                    imagebg_color = newcolor;
                }
            }
        }
    }
    public Analyzer(){ background_color = 0; border_color = 0; imagebg_color = 0;}
    public int background(){ return background_color; }
    public int border() { return border_color;}
    public int imagebg() {return imagebg_color;}
    public int analyze(String filename,String what) throws IOException{
        image = ImageIO.read(new File(filename));
        pixdata = new int[image.getHeight()][image.getWidth()];
        populateRGB();
        if(what.equals("background"))return background();
        if(what.equals("border"))return border();
        if(what.equals("image-background"))return imagebg();
        else return 0;
    }
}
public class ImageAnalyze{
    public static void main(String[] args){
        Analyzer an = new Analyzer();
        String imageName;

        Scanner scan = new Scanner(System.in);
        System.out.print("Enter image name:");
        imageName = scan.nextLine();
        try{
        int a = an.analyze(imageName,"border");//"border","image-background","background" will get you different colors
        System.out.printf("Color bg: %x",a);

        }catch(Exception e){
           System.out.println(e.getMessage());
        }
    }
}

возвращенный цвет - формат ARGB. Вам нужно будет извлечь R, G и B из него.

В этом коде есть ошибка. Работа над реализацией с использованием конечного автомата. в первом состоянии выНаходясь внутри изображения, следовательно, 0,0 - цвет фона, затем, когда есть изменение, изменение - цвет границы, затем третье состояние - когда внутри изображения + внутри границы и цвет меняется.

 Voldemort21 окт. 2012 г., 08:22
Как, начиная с начальной позиции Пикселя, а затем идти по диагонали вниз-вправо? Но если я это сделаю, есть вероятность (вероятно, на изображении, которое я предоставил), что результат будет желтым, а не ожидаемым белым. Потому что в этом случае initialPixel находится так далеко, что, если вы уйдете по диагонали вниз вправо, вполне вероятно, что вы нажмете желтый вместо белого. Если нет, то просто представьте, что черная рамка немного больше.
 Aniket Inge21 окт. 2012 г., 08:24
Вы можете игнорировать определенный цвет (прозрачный), (в данном случае желтый). Определите, чтоs граница (черная в данном случае)
 Voldemort21 окт. 2012 г., 08:26
Я могу'не принимать во внимание желтый, потому что также возможно, что фигураs также действительно желтый цвет фона (рисунокфон и холст цвета фона могут быть одинаковыми - в данном случае это не так, но в любом случае это возможно).
Решение Вопроса

графикгде есть один узел ('составная часть' в этом ответе) для каждого цвета закрашенной области.

Вот один из способов реализации этого подхода:

Пометить все пиксели как не посещенные.

Для каждого пикселя, если он не посещен, выполнитезаливка алгоритм на нем. Во время заливки отметьте каждый подключенный пиксель как посещенный.

Теперь у вас должен быть список областей сплошного цвета на вашем изображении (иликомпоненты'), так что вам просто нужно выяснить, как они связаны друг с другом:

Найдите компонент, пиксели которого расположены рядом с компонентом цвета фона - это граница вашей фигуры. Обратите внимание, что вы можете найти компонент цвета фона, найдя компонент с 0,0 пикселем.

Теперь найдите компоненты с пикселями рядом с недавно найденнымфигурная граница составная часть. Будет два таких компонента - выберите тот, который нет фон (то есть это нет 0,0 пикселя). Это фон вашей фигуры.

Чтобы найти группы пикселей, просто посчитайте количество компонентов с пикселями, смежными с компонентом фона рисунка (игнорируя, конечно, компонент границы рисунка)

Преимущества этого подхода:

работает в O (# пикселей) времени.легко понять и реализовать.Безразлично»Предполагается, что цвет фона и цвет фона фигуры различны.

Чтобы убедиться, что вы понимаете, как могут работать итерации компонентов и их соседей, здесь 'Пример реализации псевдокода для шага 5:

List<component> allComponents; // created in step 2
Component background; // found in step 3 (this is the component with the 0,0 pixel)
Component figureBorder; // found in step 4
List<component> pixelGroups = new List<component>(); // list of pixel groups

for each Component c in allComponents:
    if c == background:
        continue;
    for each Pixel pixel in c.pixelList:
        for each Pixel neighbor in pixel.neighbors:
            if neighbor.getComponent() == figureBorder:
                c.isPixelGroup = true;

int numPixelGroups = 0;
for each Component c in allComponents:
    if (c.isPixelGroup)
        numPixelGroups++;
</component></component></component>
 Voldemort01 нояб. 2012 г., 02:46
В конце я понял, что это работает с твоей идеей. Благодарю.
 Cam01 нояб. 2012 г., 05:12
@ Омега: Этоприятно слышать - извините, я пропустил ваш комментарий выше!
 Voldemort23 окт. 2012 г., 01:19
Спасибо, это звучит как отличная идея, и теперь ям в середине попробовать это. Я'дам вам знать, как идут дела :). У меня есть вопрос о шаге 5: что делать, если мне нужно узнать, сколько групп пикселей делаетопределенная фигура есть? Я имею в виду, по-видимому, ваш пример найдет все группы пикселей на всем изображении, но мне, возможно, придется сказать: «Есть фигура зеленого цвета с двумя группами, а другая фигура зеленого цвета с пятью группами "

Ваш ответ на вопрос