Тиснение изображения

#image #scheme #iteration

#изображение #схема #итерация

Вопрос:

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

   (define bound
      (lambda (n)
        (cond
          [(<= n 0) 0]
          [(>= n 255) 255]
          [else n])))
  

Bound принимает целое число и обрезает значения за пределами диапазона от 0 до 255 включительно до конечных точек.

 (define boost
  (lambda (x)
    (bound (  127 x))))
  

Boost принимает целое число, добавляет к нему 127, а затем ограничивает результат. Число 127 находится в центре внимания boost, потому что мы будем использовать boost для усиления цветов, а 127 — это половина диапазона цветового компонента.

 (define image-emboss
  (lambda (img)
    (define emboss
      (lambda (r c)
        (let ([a (image-ref img r (add1 c))]
              [b (image-ref img (add1 r) (add1 c))]
              [c (image-ref img (sub1r) (add1 c))]
              [d (image-ref img r (sub1 c))]
              [e (image-ref img (sub1 r) (sub1 c))]
              [f (image-ref img (add1 r) (sub1 c))])
          (if (or (< r 0) (< c 0))
              img
              (make-image r c (boost (- (  a b c) d e f)))))))
  (emboss r c)))
  

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

Требуется изображение в пикселях

Я попытался создать image-emboss: он берет изображение и возвращает тисненую версию изображения. Пиксели по периметру не изменились. Предполагается, что в этой процедуре будут использоваться make-image и image-ref.

Image-rows извлекает изображение и возвращает количество строк в изображении.

 (define image-rows
  (lambda (img)
    (cond
     [(image? img 1 1) (vector-length (img))]
     [else
      (error 'image-rows (format "~a is not an image" img))])))
  

Image-cols принимает изображение и возвращает количество столбцов в изображении.

 (define image-cols
  (lambda (img)
    (cond
     [(image? img 1 1) (if (zero? (vector-length (img)))
                           0
                           (vector-length (vector-ref (img) 0)))]
     [else
      (error 'image-cols (format "~a is not an image" img))])))
  

Image-ref принимает изображение, индекс строки и индекс столбца и возвращает пиксель.

 (define image-ref
  (lambda (img r c)
    (if (not (image? img 0 0))
        (error 'image-ref "first argument is not an image"))
    (if (and (integer? r) (<= 0 r (- (image-rows img) 1)))
        (if (and (integer? c) (<= 0 c (- (image-cols img) 1)))
            (vector-ref (vector-ref (img) r) c)
            (error 'image-ref (format "~a is an illegal index" c)))
        (error 'image-ref (format "~a is an illegal index" r)))))
  

Make-image принимает строки, столбцы и процедуру.

 (define make-image
  (lambda (rows cols . args)
    (let ([gen-proc
           (cond
            [(null? args) (lambda (i j rows cols) black)]
            [(not (null? (cdr args)))
             (error 'make-image "too many arguments")]
            [(color? (car args)) (lambda (i j rows cols) (car args))]
            [(procedure? (car args)) (car args)]
            [else (error 'make-image (format "unknown fill: ~s" 
                                             (car args)))])])
      (let ([img (make-vector rows)])
        (let loop ([i 0])
          (when (< i rows)
            (vector-set! img i 
                         (let ([row (make-vector cols)])
                           (let loop ([j 0])
                             (when (< j cols)
                               (vector-set! row j (gen-proc i j rows cols))
                               (loop (  j 1))))
                           row))
            (loop (  i 1))))
        (lambda () img)))))
  

Способ, которым я тестирую это, заключается в загрузке изображения и определении его в repl, затем рисовании изображения с использованием процедуры, созданной моим профессором.

В любом случае. Я думаю, что мой код близок к правильному, но я действительно не уверен, как это исправить. Если у кого-нибудь есть подсказка / лучшее объяснение, которое поможет мне разобраться в этом, я был бы очень признателен. Спасибо

Ответ №1:

Хотя я не уверен, какие еще проблемы вы видите, одна вещь, которая поражает меня сразу, заключается в том, что image-emboss функция, похоже, на данный момент не имеет правильного потока оценки. Из того, что я вижу, когда вы вызываете image-emboss , вы передаете ему изображение, после чего он вычисляет лямбда-выражение, которое вычисляет лямбда-выражение для emboss , а затем вызывает emboss со значениями r и c … но вы не определили r и c в среде (то есть фрейме среды, созданном image-emboss лямбдой), внутри которого emboss выполняется вызов. Как тогда интерпретатор схемы может оценить два символа r и c для правильного вызова лямбда-выражения, определенного emboss ?

Я бы подумал, что, по крайней мере, ваш вызов emboss inside of image-emboss должен выглядеть скорее как (emboss (image-rows img) (image-cols img)) , чем (emboss r c) . Вызов (emboss (image-rows img) (image-cols img)) содержит символы, которые все могут быть оценены в среде-фрейме, определенном image-emboss (emboss r c) с другой стороны, этого не происходит.

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

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

Джейсон

Комментарии:

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

2. В любом случае, то, что я должен был сделать, это определить два цикла, r и c, как (sub1 (изображение-строки изображения)) и (sub1 (изображение-столбцы изображения)). Затем, когда r и c равны > = 0, приступайте к тиснению изображения и элемента 1 из r и c на каждой итерации.