Tamer Hatoum Ответов: 2

Обнаружение сканируемой области ( определение цвета)


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

Любое тело есть какие-либо идеи ???
с уважением..

2 Ответов

Рейтинг:
17

Johannes Hillert

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

class Color
{
    // Color components
    public int R, G, B;

    // Set color components
    public void SetColor(int R, int G, int B)
    {
        this.R = R;
        this.G = G;
        this.B = B;
    }

    // Basic check, if the pixel is black
    public bool isBlack()
    {
        if (R == 0 && G == 0 && B == 0)
        {
            return true;
        }

        return false;
    }

    // Routine for output purposes
    public override string ToString()
    {
        return "(" + R.ToString() + "," + G.ToString() + "," + B.ToString() + ")";
    }
}


Теперь нам нужен двухмерный массив, который служит изображением, я просто использую матрицу 4x4 для этого примера.

int width = 4, height = 4;

Color[,] image = new Color[height, width];


Изображение должно быть инициализировано. Вы сказали, что у вашего изображения есть черный край, поэтому давайте сделаем изображение с черной рамкой и некоторыми цветными данными в центре, что-то вроде этого:

// Example image:
//
// B B B B
// B C C B
// B C C B
// B B B B
//
// B - black
// C - color


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

// 1. Line
image[0, 0] = new Color();
image[0, 0].SetColor(0, 0, 0);

// [..]

// 2. Line
image[1, 0] = new Color();
image[1, 0].SetColor(0, 0, 0);
image[1, 1] = new Color();
image[1, 1].SetColor(255, 0, 0);
image[1, 2] = new Color();
image[1, 2].SetColor(0, 0, 255);

// [..]

// 3. Line
image[2, 0] = new Color();
image[2, 0].SetColor(0, 0, 0);
image[2, 1] = new Color();
image[2, 1].SetColor(0, 255, 0);
image[2, 2] = new Color();
image[2, 2].SetColor(255, 255, 0);

// [..]

image[3, 3] = new Color();
image[3, 3].SetColor(0, 0, 0);


Я предоставлю вам ссылку на полный исходный код примера в конце, так что если возникнут какие-либо вопросы, просто взгляните на исходный код.

Чтобы позже иметь возможность сравнить входные данные с результатом, давайте посмотрим данные изображения.

// "Show" the image
Console.WriteLine("Old Image:\n");

for (int y = 0; y < height; y++)
{
    for (int x = 0; x < width; x++)
    {
        Console.Write(image[y, x].ToString() + " ");
    }

    Console.WriteLine();
}


Следующая часть более интересна для вас, я думаю. Как я уже говорил в своем первом решении, мое предложение состоит в том, чтобы найти минимальные и максимальные значения X и Y цветной области на вашем изображении и скопировать эту область в новое изображение. Во-первых, давайте найдем эти минимальные и максимальные значения.

int minX = 0,
    maxX = 0,
    minY = 0,
    maxY = 0;

bool gotMin = false;

for (int y = 0; y < height; y++)
{
    for (int x = 0; x < width; x++)
    {
        if (!image[y, x].isBlack())
        {
            if (!gotMin)
            {
                minX = x;
                minY = y;

                gotMin = true;
            }

            if (x > maxX) maxX = x;
            if (y > maxY) maxY = y;
        }
    }
}


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

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

int newWidth = maxX - minX + 1;
int newHeight = maxY - minY + 1;

Color[,] newImage = new Color[newHeight, newWidth];

for (int y = minY; y <= maxY; y++)
{
    for (int x = minX; x <= maxX; x++)
    {
        newImage[y - minY, x - minX] = new Color();
        newImage[y - minY, x - minX].SetColor(image[y, x].R, image[y, x].G, image[y, x].B);
    }
}


И наконец, давайте посмотрим на результат и сравним его с входными данными.

// "Show" new image
Console.WriteLine("New Image:\n");

for (int y = 0; y < newHeight; y++)
{
    for (int x = 0; x < newWidth; x++)
    {
        Console.Write(newImage[y, x].ToString() + " ");
    }

    Console.WriteLine();
}


Конечно, вы могли бы использовать другие методы для отображения вашего изображения, консольные вещи здесь просто дают вам пример.

Ну, в основном это то, о чем я говорил в своем первом решении.

Надеюсь, это поможет.

Ура!


Связи

Исходный код
Итерационный анализ для построения алгоритма (изображение)


Dave Kreskowiak

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

Johannes Hillert

Измените "if (R == 0 & G == 0 & B == 0)" в процедуре isBlack на что-то вроде "if (R < 50 & G< 50 & B < 50)" (20% от 255 ~ 50), и вы получите порог.

Рейтинг:
0

Johannes Hillert

Как насчет того, чтобы пройти по всему изображению и найти координаты minX, maxX и minY, maxY области с цветными пикселями? Затем создайте новое изображение с width=maxX-minX и height=maxY-minY и скопируйте соответствующую область из первого изображения в новое.

Просто предложение, но я надеюсь, что это поможет.

Ваше здоровье!


Tamer Hatoum

но как найти первые цветные пиксели ??

Johannes Hillert

Ну, цветной пиксель-это ведь не черный, верно? Для черных пикселей значения красного, зеленого и синего равны нулю. Отрицайте это утверждение, и вы знаете, что пиксель является цветным.

Хорошо, я дам вам более подробное представление о том, как, по моему мнению, вы могли бы это сделать, пожалуйста, обратитесь к моему 2-му решению.

buithientin

Я не могу скачать исходный код. Пожалуйста,дайте мне, у меня есть проблема удаления черной границы, спасибо Вам большое!

Johannes Hillert

Да, к сожалению RapidShare.com перестал работать пять лет назад, но отображаемый код в решении два-это в основном то, что было в исходном коде ZIP, и должно дать вам хорошее понимание того, как решить эту проблему.

Johannes Hillert

Удивительно, но я только что нашел оригинальные файлы .. после такого долгого времени .. 😀 .. Я обновил ссылки в конце поста, так что исходный код теперь доступен на GitHub, и вы можете просмотреть изображение на рабочем сайте хостинга изображений.