Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Сделать серый цвет темнее


Автор: Akella 3.12.2013, 16:33
Есть картинка (приложил к сообщению).
Движок распознавания (tesseract) иногда очень плохо распознает цифру 1, а также точку с запятой, я имею ввиду, что вообще не распознаёт. Ну и другие символы не всегда правильно. Может из 8 сделать 3 или 5.
Хотя другие картинки почти всегда правильно. Они чётче.
Я увеличиваю картинку в 3-4 раза и подсовываю движку распознавания.
Как бы мне сделать символы более чёткими, темнее?
Спасибо.

Автор: Агрох 3.12.2013, 17:27
Писал когда то программу, которая делает слишком светлые пиксели белыми, а слишком тёмные - чёрными, получая таким образом чёрно-белое изображение. Порог светлый/тёмный можно было выставлять вручную. С помощью этой программы делал более чёткими и чистыми сканы рисунков, нарисованных карандашом на бумаге. Однажды полностью восстановил чеки, которые выцвели до нечитабельного состояния.

Могу завтра (сейчас некогда) поискать исходники. Но сразу предупрежу они сделаны на компонентах UnDelphiX. Хотя думаю под обычный канвас алгоритм переделать легко.

Автор: Akella 3.12.2013, 17:38
Цитата(Агрох @  3.12.2013,  17:27 Найти цитируемый пост)
они сделаны на компонентах UnDelphiX

не, спасибо

Автор: Illusion Dolphin 3.12.2013, 22:18
Увеличьте контрастность
Код


procedure Contrast(Image: TBitmap; Value: Extended; Local: Boolean);

  function BLimit(B: Integer): Byte; inline;
  begin
    if B < 0 then
      Result := 0
    else if B > 255 then
      Result := 255
    else
      Result := B;
  end;

var
  Dest : pRGBTriple;
  x, y, mr, mg, mb,
    W, H, tr, tg, tb: Integer;
  vd: Double;

begin
 Image.PixelFormat := pf24bit;

 W := Image.Width - 1;
 H := Image.Height - 1;
  if Local then
  begin
    mR := 128;
    mG := 128;
    mB := 128;
  end else
  begin
    tr := 0;
    tg := 0;
    tb := 0;
    for y := 0 to H do
    begin
      Dest := Image.ScanLine[y];
      for x := 0 to W do
      begin
        with Dest^ do
        begin
          Inc(tb, Dest^.rgbtRed);
          Inc(tg, Dest^.rgbtGreen);
          Inc(tr, Dest^.rgbtBlue);
        end;
        Inc(Dest);
      end;
    end;
    mB := Trunc(tb / (W * H));
    mG := Trunc(tg / (W * H));
    mR := Trunc(tr / (W * H));
  end;
  if Value > 0 then
    vd := 1 + (Value / 10)
  else
    vd := 1 - (Sqrt(-Value) / 10);
  for y := 0 to H do
  begin
    Dest := Image.ScanLine[y];
    for x := 0 to W do
    begin
      with Dest^ do
      begin
        rgbtRed := BLimit(mB + Trunc((rgbtRed - mB) * vd));
        rgbtGreen := BLimit(mG + Trunc((rgbtGreen - mG) * vd));
        rgbtBlue := BLimit(mR + Trunc((rgbtBlue - mR) * vd));
      end;
      Inc(Dest);
    end;
  end;
end;

Автор: Alexeis 4.12.2013, 08:32
Чтобы увеличить яркость, по хорошему цвета из RGB нужно перевести в HSV схему http://ru.wikipedia.org/wiki/HSV_(%D1%86%D0%B2%D0%B5%D1%82%D0%BE%D0%B2%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C)

В ней последний параметр яркость. Добавляем яркости и обратно в RGB конвертим.

Автор: Alexeis 4.12.2013, 09:41
Akella, попробуй еще фильтр фотошопа unsharp mask . Он вроде как улучшается края как раз. 

Автор: Akella 4.12.2013, 09:57
А если нет на ПК фотошопа?


Illusion Dolphin, пасиб, попробую.
Получает, что JPG или PNG нужно конвертнуть в BMP, увеличить контрастность, а затем обратно в PNG? Качество не потеряется?

Добавлено через 4 минуты и 55 секунд
Цитата(Illusion Dolphin @  3.12.2013,  22:18 Найти цитируемый пост)
procedure Contrast(Image: TBitmap; Value: Extended; Local: Boolean);


ещё вопрос, что такое Value и Local, и как их применять?

Автор: Агрох 4.12.2013, 10:06
Цитата(Akella @  3.12.2013,  18:38 Найти цитируемый пост)
Цитата(Агрох @  3.12.2013,  17:27 )
они сделаны на компонентах UnDelphiX

не, спасибо 


Какое предвзятое мнение, как о новичках на форуме, так и о незнакомых компонентах.

Там через UnDelphiX только вывод на экран. Обработка пикселей через Canvas.Pixels[x, y], выделение rgb составляющих пикселя и их анализ.

Автор: Alexeis 4.12.2013, 10:35
Цитата(Akella @  4.12.2013,  10:57 Найти цитируемый пост)
Получает, что JPG или PNG нужно конвертнуть в BMP, увеличить контрастность, а затем обратно в PNG? Качество не потеряется?

  Жпег плохо использовать для текста, потому что как раз жпег больше других форматов портит края текста, контуров и вообще любых чертежей. PNG формат без потерь, так что PNG<->BMP не приведет к ухудшению качества.

Цитата(Akella @  4.12.2013,  10:57 Найти цитируемый пост)
А если нет на ПК фотошопа?

Этот фильтр есть в Гимпе. Программно это реализуется с помощью гаусова размытия + дополнительные арифметические операции. Вот кстати описание этого фильтра и описание как его реализовать http://docs.gimp.org/en/plug-in-unsharp-mask.html . Фильтры гауса несложно найти в интернете готовую реализацию, а вычитать и складывать цвета пикселов, думаю ты осилишь smile .

Добавлено через 1 минуту и 55 секунд
Да чо уж там в интернетах, у нас на форуме есть реализация gaussian blur http://forum.vingrad.ru/faq/topic-157073.html

Автор: Агрох 4.12.2013, 10:38
Да, получилось немного не так, как думал.
Файл после обработки прикреплён к ответу.

Если нужны исходники, прикреплю. Без UnDelphiX.
Прога работает с jpg. Т.е. открывает их, но потом загружает файл в TImage и с ним уже работает. Сохраняет тоже в Jpg.

Автор: Akella 4.12.2013, 11:44
Цитата(Alexeis @  4.12.2013,  10:35 Найти цитируемый пост)
 Жпег плохо использовать для текста, потому что как раз жпег больше других форматов портит края текста, контуров и вообще любых чертежей. PNG формат без потерь, так что PNG<->BMP не приведет к ухудшению качества.


ок, понял

Добавлено через 56 секунд
Цитата(Агрох @  4.12.2013,  10:06 Найти цитируемый пост)
Какое предвзятое мнение, как о новичках на форуме, так и о незнакомых компонентах.


при чём здесь мнение, если я просто не хочу использовать сторонние компоненты только из-за 1-2 процедур или функций, не вижу смысла пока что

Добавлено через 2 минуты и 10 секунд
Цитата(Alexeis @  4.12.2013,  10:35 Найти цитируемый пост)
Этот фильтр есть в Гимпе. 

таскать с собой гимп и фильтр?
зачем, если Illusion Dolphin дал готовый вариант
вариант этот работает, текст становится темнее, распознавание улучшилось, это факт

Добавлено через 2 минуты и 50 секунд
Цитата(Агрох @  4.12.2013,  10:38 Найти цитируемый пост)
Файл после обработки прикреплён к ответу. 

у меня так же получается smile 

Автор: Агрох 4.12.2013, 11:49
Цитата(Akella @  4.12.2013,  12:44 Найти цитируемый пост)
при чём здесь мнение, если я просто не хочу использовать сторонние компоненты только из-за 1-2 процедур или функций, не вижу смысла пока что


Извини. Не понял. Просто люди как слышат про эти компоненты обычно сразу начинают нос воротить.

Нашёл исходники и адаптировал их под TImage, без UNDelphiX. Хотя там и так через Canvas всё делалось. Пример результата работы можно посмотреть выше. Могу выложить исходники.

Автор: Alexeis 4.12.2013, 15:04
Цитата(Akella @  4.12.2013,  12:44 Найти цитируемый пост)
таскать с собой гимп и фильтр?
зачем, если Illusion Dolphin дал готовый вариант
вариант этот работает, текст становится темнее, распознавание улучшилось, это факт

  Ну я вообще имел ввиду, потестировать на предмет улучшиться ли распознавание после unsharp mask. Я в свое время как раз этот фильтр использовал для улучшения качества краев текста, но сейчас глянул на твой текст и думаю, что пожалуй мелковат он для любых фильтров.

Автор: Akella 4.12.2013, 15:43
цифры распознаются в принципе нормально, увеличиваю картинку в три раза и норма, но такие мелочи, как точка и запятая, а также точка запятой.... не очень,
примерно в 30% случаев не распознается

Автор: PointerToNil 5.12.2013, 17:43
если нужно сделать темнее:
Код

real_c := c / 255; // диапазон 0..255 -> 0..1
new_real_c := real_с * real_c; // уменьшаем гамму (сильно)
factor := 0.5; // если нужно не так сильно, то смешаем со старым значением: 
new_real_c := new_real_c * factor + real_c * (1 - factor); // factor ближе к 1 - сильнее
new_с := round( new_real_c * 255 ); // диапазон обратно -> 0..255
и так - с каждой из компонент цвета (r, g, b) каждой точки
(подразумевалась под "c" и "new_c")

если контрастнее - немного иначе:
Код

real_c := c * 2 / 255 - 1; // диапазон 0..255 -> -1..1
if real_c >= 0 then
  new_real_c := sqrt(real_с) // для яркой половины цветов "диапазонную гамму" увеличиваем 
else
  new_real_c := -sqrt(-real_c); // для темной - уменьшаем
factor := 0.5; // если нужно не так сильно, то смешаем со старым значением: 
new_real_c := new_real_c * factor + real_c * (1 - factor); // factor ближе к 1 - сильнее
new_с := round( (new_real_c + 1) * 255 / 2 ); // диапазон обратно -> 0..255
(код не тестировал)

Автор: Агрох 9.12.2013, 11:07
Попробуй мой вариант. Проект прикреплён.

Там на форме два трекбара. Первый отвечает за степень очистки от слишком светлых пикселей, второй за очернение достаточно тёмных. Соответственно при нулях на обоих ничего не изменится, при 255 на отбеливании, почти все пиксели станут белыми (r=255, g=255, b=255), при 255 на очернении все пиксели, кроме белых, будут чёрными (r=0, g=0, b=0).

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

Есть 4 Image, слева оригинал и увеличенный в 5 раз оригинал, справа - обработанное изображение и увеличенное в 5 раз обработанное изображение.

При коэффициентах 64, 191 изображения в bmp состоит только из чёрных и белых пикселей. В jpg немного "мусора" появляется.

Можно поиграть с коэффициентами, может что получится.

Автор: Illusion Dolphin 9.12.2013, 16:44
Код

     temp1_s := inttohex(Image1.Canvas.Pixels[x_pix,y_pix], 6);
      r1 := StrToInt('$' + temp1_s[5] + temp1_s[6]);
      g1 := StrToInt('$' + temp1_s[3] + temp1_s[4]);
      b1 := StrToInt('$' + temp1_s[1] + temp1_s[2]);

      iFactor := 255 - TrackBar1.Position;
      ...
      Image2.Canvas.Pixels[x_pix, y_pix] := r1 + g1*256 + b1*65536;

(facepalm) Чудеса оптимизации

Автор: Агрох 9.12.2013, 16:53
Illusion Dolphin, это урезанная версия под конкретную задачу. Уверяю вас, в полной версии всё то, что вам кажется не оптимизированным, использовалось.

Главный вопрос: работает ли?

Автор: Akella 9.12.2013, 17:00
Я не пробовал, ибо уже отдал программу пользователю с кодом, который предоставил Illusion Dolphin. Пока всё хорошо.

Автор: Alexeis 9.12.2013, 17:03
Цитата(Агрох @  9.12.2013,  12:07 Найти цитируемый пост)
При коэффициентах 64, 191 изображения в bmp состоит только из чёрных и белых пикселей. В jpg немного "мусора" появляется.

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

Картинка под увеличением демонстрирует лучше всяких слов.
user posted image

Цитата(Агрох @  9.12.2013,  17:53 Найти цитируемый пост)
Уверяю вас, в полной версии всё то, что вам кажется не оптимизированным, использовалось.

   Кто спорит, что работает. Для картинки 100х20 жить будет. Дело в том, что производительность сего кода примерно раз 500 хуже того что можно было сделать. 

Автор: Агрох 9.12.2013, 17:13
Цитата(Alexeis @  9.12.2013,  18:03 Найти цитируемый пост)
 Jpeg не бывает черно-белым. Или 256 оттенков серого или тру колор. Пожимать чертежи жпегом худшее из того что можно придумать. Во-первых сжатие получается хуже чем png, а второе это размытие линий, которое ни разу не облегчает бинаризацию и выделение контуров.


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

В самой программе работа идёт через Image.Canvas.Pixels[x,y], т.е. обработки именно изображения jpg нету. Просто можно открыть файл jpg, прога его преобразует в bitmap, обрабатывает, а полученный bitmap обратно сохраняет в jpg. Качество открытия/сохранения jpg на совести библиотеки JPEG.

Автор: Агрох 10.12.2013, 16:18
Цитата(Alexeis @  9.12.2013,  18:03 Найти цитируемый пост)
Кто спорит, что работает. Для картинки 100х20 жить будет. Дело в том, что производительность сего кода примерно раз 500 хуже того что можно было сделать. 


Есть задача и есть решение. В условии задачи, той которую я ставил перед собой когда это делал, не было добиться максимальной производительности. А её можно добиться разве что используя для решения возможности видеокарты, DirectX или OpenGL.

На всякий случай ещё уточню, что в полной версии работа производилась не с двумя цветами, чёрным и белым (rgb (0,0,0) и (255,255,255)) а со всеми цветами диапазона. Настройка осуществлялась не двумя TrackBara-ами, а восемью, плюс было две опции в RadioGroup. Это на тему лишних переменных в коде и ненужных преобразований.

В то время я слегка увлёкся графикой, в том числе и сам рисовал контурные рисунки карандашом на бумаге. В первую очередь меня интересовала возможность очистки сканов этих самых рисунков от грязи, которая непременно возникала в процессе рисования (многократное стирание неудавшихся линий и рисование по новой) и повышение чёткости линий рисунков, для последующей работы с ними в программах обработки графики. Это было лет 5 назад, когда я ещё толком даже ООП не освоил, и программированием занимался всего около 2-х лет. Естественно код не оптимизирован. Сейчас же я чисто косметические изменения в него внёс.
Повышение контрастности - не выход, т.к. повышается контрастность не только самого рисунка но и артефактов. Вручную удалять всё это было лень.
Высокая производительность не нужна была, т.к. максимум мне надо было обработать 1-2 рисунка в день. Главное, чтобы работало. И оно работало.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)