Как убрать серый фон с отсканированного изображения

Я написал небольшой Java SANE-клиент для Windows с использованием библиотеки jfreesane, и некоторое время он работал хорошо, но вчера я обнаружил проблему со сканером CanoScan LiDE 60 — при использовании «оттенков серого». » на отсканированном изображении серый фон, и я не знаю, как от этого избавиться. Вот о чем я говорю:

введите здесь описание изображения

Я столкнулся с этой проблемой на некоторых других сканерах и решил ее, настроив параметр контрастность, однако у CanoScan LiDE 60 его нет. Вот полный список параметров из вывода "scanimage -A" (я пробовал все, что относится к цвету, кроме gamma-table):

All options specific to device `genesys:libusb:003:002':
  Scan Mode:
    --mode Color|Gray|Lineart [Gray]
        Selects the scan mode (e.g., lineart, monochrome, or color).
    --source Flatbed|Transparency Adapter [inactive]
        Selects the scan source (such as a document-feeder).
    --preview[=(yes|no)] [no]
        Request a preview-quality scan.
    --depth 8|16 [8]
        Number of bits per sample, typical values are 1 for "line-art" and 8
        for multibit scans.
    --resolution 1200|600|300|150|75dpi [75]
        Sets the resolution of the scanned image.
  Geometry:
    -l 0..218mm [0]
        Top-left x position of scan area.
    -t 0..299mm [0]
        Top-left y position of scan area.
    -x 0..218mm [218]
        Width of scan-area.
    -y 0..299mm [299]
        Height of scan-area.
  Enhancement:
    --custom-gamma[=(yes|no)] [no]
        Determines whether a builtin or a custom gamma-table should be used.
    --gamma-table 0..65535,... [inactive]
        Gamma-correction table.  In color mode this option equally affects the
        red, green, and blue channels simultaneously (i.e., it is an intensity
        gamma table).
    --red-gamma-table 0..65535,... [inactive]
        Gamma-correction table for the red band.
    --green-gamma-table 0..65535,... [inactive]
        Gamma-correction table for the green band.
    --blue-gamma-table 0..65535,... [inactive]
        Gamma-correction table for the blue band.
    --swdeskew[=(yes|no)] [no]
        Request backend to rotate skewed pages digitally
    --swcrop[=(yes|no)] [no]
        Request backend to remove border from pages digitally
    --swdespeck[=(yes|no)] [no]
        Request backend to remove lone dots digitally
    --despeck 1..9 (in steps of 1) [1]
        Maximum diameter of lone dots to remove from scan
    --swskip 0..100% (in steps of 1) [0]
        Request driver to discard pages with low numbers of dark pixels
    --swderotate[=(yes|no)] [no]
        Request driver to detect and correct 90 degree image rotation
  Extras:
    --lamp-off-time 0..60 [15]
        The lamp will be turned off after the given time (in minutes). A value
        of 0 means, that the lamp won't be turned off.
    --lamp-off-scan[=(yes|no)] [no]
        The lamp will be turned off during scan.
    --threshold 0..100% (in steps of 1) [50]
        Select minimum-brightness to get a white point
    --threshold-curve 0..127 (in steps of 1) [50]
        Dynamic threshold curve, from light to dark, normally 50-65
    --disable-dynamic-lineart[=(yes|no)] [no]
        Disable use of a software adaptive algorithm to generate lineart
        relying instead on hardware lineart.
    --disable-interpolation[=(yes|no)] [no]
        When using high resolutions where the horizontal resolution is smaller
        than the vertical resolution this disables horizontal interpolation.
    --color-filter Red|Green|Blue|None [None]
        When using gray or lineart this option selects the used color.
  Sensors:
  Buttons:
    --clear-calibration
        Clear calibration cache

И вот что интересно: Simple Scan (программа сканирования для Linux) каким-то образом умудряется удалять серый цвет с изображения с помощью этого сканера:

введите здесь описание изображения

Я не уверен, использует ли он какую-то обработку после сканирования или знает, как сообщить сканеру о контрасте. Если это первое, есть ли какие-либо библиотеки Java, которые могут удалить этот серый шум?


person Vladimir M.    schedule 22.06.2016    source источник
comment
Я подозреваю, что Simple Scan использует постобработку и просто бинаризирует изображение. То есть: установите Threshold, любой пиксель с grey-val › t установите на 255, иначе установите на 0. Вы пробовали линейный режим, не так ли?   -  person Fildor    schedule 22.06.2016
comment
@Fildor Да, я пробовал линейную графику с разными пороговыми значениями, но результат был ужасен: черные точки и пятна по всему изображению, а буквы стали четкими.   -  person Vladimir M.    schedule 22.06.2016
comment
В режиме Lineart вы пытались поиграться с удалением пятен? (--swdespeck и --despeck)   -  person Fildor    schedule 22.06.2016
comment
Очистка результатов сканирования — это искусство, знаете ли :)   -  person Fildor    schedule 22.06.2016


Ответы (1)


После некоторых тестов я остановился на этой функции (формула контраста была взята из здесь):

public void processImage(BufferedImage bimg, int brightness, int contrast, int t_black, int t_white) {
        Color c;
        int r, g, b;
        float factor = (259f * (contrast + 255f)) / (255f * (259f - contrast));

        for (int x = 0; x < bimg.getWidth(); x++)
            for (int y = 0; y < bimg.getHeight(); y++) {
                c = new Color(bimg.getRGB(x, y));
                // apply brightness and contrast
                r = Math.round(factor * (c.getRed() - 128) + 128) + brightness;
                g = Math.round(factor * (c.getGreen() - 128) + 128) + brightness;
                b = Math.round(factor * (c.getBlue() - 128) + 128) + brightness;
                // limit to [0, 255] range
                r = Math.min(255, Math.max(0, r));
                g = Math.min(255, Math.max(0, g));
                b = Math.min(255, Math.max(0, b));
                // apply black and white thresholds
                if (r < t_black && g < t_black && b < t_black)
                    bimg.setRGB(x, y, 0);
                else if (r > t_white && g > t_white && b > t_white)
                    bimg.setRGB(x, y, 255 << 16 | 255 << 8 | 255);
                else
                    bimg.setRGB(x, y, r << 16 | g << 8 | b);
            }
    }    
person Vladimir M.    schedule 24.06.2016