#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 на каждой итерации.