Обрезать темное пространство из фотографии в PHP - PullRequest
0 голосов
/ 14 декабря 2011

Это сообщение является продолжением вопроса, заданного пару лет назад здесь: Обрезать пробелы на изображении в PHP

Этот пост прекрасно объясняет, как использовать php для обрезкичистый пробел вокруг изображения.Проблема здесь в том, что он ожидает "чистый белый" вокруг изображения.Вот что я пытаюсь сделать и чем он отличается:

Я использую свой мобильный телефон в качестве «сканера», чтобы снимать документы и затем загружать их на свой сервер (не волнуйтесь ...здесь не происходит ничего «секретного агента» ... на самом деле это в основном квитанции от обедов, а иногда и визиток).В моем случае я всегда стараюсь использовать темный фон для контрастирования со светлой цветной бумагой.Изображения никогда не получаются с "чистыми" черными / белыми цветами как бы то ни было.Мое изображение всегда в формате JPG.Я экспериментирую с кодом, упомянутым выше (но поменялся местами для проверки на темную / черную границу), и мне интересно, есть ли способ обобщить функцию для более широкого применения?Я могу установить ImageMagick и использовать trimImage и некоторые другие вещи, но я предпочел бы придерживаться GD, поскольку это будет более полезным для большего количества пользователей StackOverflow.Вот что я думал до сих пор:

IDEA # 1: преобразовать изображение в оттенки серого и получить очень высокий контраст ... сделайте сравнение там (предположительно с чистым черным в этой точке) ... затемиспользуйте найденные координаты на исходном (не в оттенках серого) изображении.Как вы думаете ... хороший подход?Будет ли это работать?Я бы использовал imagefilter ($ img, IMG_FILTER_GRAYSCALE);и затем imagefilter ($ img, IMG_FILTER_CONTRAST, -90);

ИДЕЯ # 2: Перейти универсальный.Это идея, в которой я нуждаюсь больше всего.Было бы очень здорово, если бы я мог автоматически определять приблизительный диапазон цветов от границы.Идея заключалась бы в том, чтобы выбрать пиксель (или несколько) из каждого из четырех углов, а затем «усреднить» их, чтобы выяснить фон.Это означало бы, что однажды, если я захочу сделать фотографию на коричневом фоне, красном фоне или зеленом фоне ... нет проблем.Я думаю, что первый шаг в этом направлении будет включать использование imagecolorclosest (), но, честно говоря, я в курсе того, как выбирать, сравнивать, усреднять, а затем повторно сравнивать цвета.В идеале был бы способ просто подключить часть этой логики к исходной функции (по ссылке выше), и тогда он мог бы работать в общем случае независимо от того, какой цвет фона в изображении (при условии, что он достаточно последовательный) и будетработать с фотографией (то есть с изображением, где цвет фона не совсем одинаковый по цвету).

Итак ... вопрос, состоящий из двух частей: мой IDEA # 1 лучший подход и есть ликакие-либо проблемы, которые я должен знать или предложения по улучшению / реализации?И ... кто-нибудь хочет попробовать IDEA # 2 и хотя бы дать мне достаточно кода, чтобы двигаться в правильном направлении?

1 Ответ

0 голосов
/ 14 декабря 2011

Так что я пошел дальше и поиграл с IDEA # 1, и он работает исключительно хорошо.Я полностью настроен и не нуждаюсь в дальнейшей помощи на данный момент ... хотя все еще думаю, что IDEA # 2 - лучшее универсальное решение, поэтому, если кто-то захочет предоставить некоторые указания для этого, я поиграю с идеями и попробуюпридумать дополнительные примеры кода для публикации здесь.На данный момент, вот моя рабочая версия IDEA # 1, как описано выше и проверено на нескольких изображениях мобильного телефона:

//MANY THANKS TO: http://stackoverflow.com/questions/1669683/crop-whitespace-from-image-in-php    

$OriginalImageFileLocation = 'sampleimage.jpg';

    //load the image into a variable (and throw an error if image does not exist)
    if( !$img = imagecreatefromjpeg("$OriginalImageFileLocation") )
    { exit("Could not use image $OriginalImageFileLocation"); } 

    // This function only can detect the background if it is "pure black"...so convert to greyscale then crank the contrast
    imagefilter($img, IMG_FILTER_GRAYSCALE);
    imagefilter($img, IMG_FILTER_CONTRAST, -100);


    //find the size of the borders
    $b_top = 0;
    $b_btm = 0;
    $b_lft = 0;
    $b_rt = 0;

    //top
    for(; $b_top < imagesy($img); ++$b_top) {
      for($x = 0; $x < imagesx($img); ++$x) {
        if(imagecolorat($img, $x, $b_top) != 0x000000) {
           break 2; //out of the 'top' loop
        }
      }
    }

    //bottom
    for(; $b_btm < imagesy($img); ++$b_btm) {
      for($x = 0; $x < imagesx($img); ++$x) {
        if(imagecolorat($img, $x, imagesy($img) - $b_btm-1) != 0x000000) {
           break 2; //out of the 'bottom' loop
        }
      }
    }

    //left
    for(; $b_lft < imagesx($img); ++$b_lft) {
      for($y = 0; $y < imagesy($img); ++$y) {
        if(imagecolorat($img, $b_lft, $y) != 0x000000) {
           break 2; //out of the 'left' loop
        }
      }
    }

    //right
    for(; $b_rt < imagesx($img); ++$b_rt) {
      for($y = 0; $y < imagesy($img); ++$y) {
        if(imagecolorat($img, imagesx($img) - $b_rt-1, $y) != 0x000000) {
           break 2; //out of the 'right' loop
        }
      }
    }

    //now re-initialize the original image since the greyscaled version was just for gathering cordinates
    $img = imagecreatefromjpeg("$OriginalImageFileLocation");

    // OPTIONAL: make the final image a bit prettier (and greyscale for long-term consistency)
    imagefilter($img, IMG_FILTER_GRAYSCALE);
    imagefilter($img, IMG_FILTER_BRIGHTNESS, +15);
    imagefilter($img, IMG_FILTER_CONTRAST, -20);


    //copy the contents, excluding the border
    $newimg = imagecreatetruecolor( imagesx($img)-($b_lft+$b_rt), imagesy($img)-($b_top+$b_btm) );
    imagecopy($newimg, $img, 0, 0, $b_lft, $b_top, imagesx($newimg), imagesy($newimg));

    //finally, output the image
    header("Content-Type: image/jpeg");
    imagejpeg($newimg);
...