2013-03-23 5 views
1

Привет, я пытаюсь нарисовать диагональные линии по изображению сверху справа внизу внизу, вот мой код.Рисование диагональных линий на изображении

width = getWidth(picture) 
    height = getHeight(picture) 
    for x in range(0, width): 
    for y in range(0, height): 
     pixel = getPixel(picture, x, y) 
     setColor(pixel, black) 

Благодаря

+1

Вы должны отметить графическую библиотеку, которую вы используете ... – MartinStettner

+0

im с использованием среды jython для студентов – user2194374

ответ

1

Где ваш picture объект приходит от? Что это? Что пока не работает? И какую библиотеку для доступа к изображениям вы пытаетесь использовать? (Я имею в виду, где вы можете получить или получить «getWidth, getHeight, getPixel, setColor)?

Я думаю, что нет библиотеки, которая дает вам« пиксель »как целого объекта, который может использоваться в setColor вызов существует, и если это произойдет, это будет самая медленная вещь в мире - возможно, в галактике.

С другой стороны, если эти методы существовали и ваше изображение, приведенный выше код будет охватывать все изображения в черный - вы получаете все возможные значения «y» (от 0 до высоты) внутри всех возможных значений x (от 0 до ширины) изображения и окрашивания каждого черного.

Для рисования линии потребуется изменить x , и y в то же время, больше похоже на:

(с использованием другого «мнимое библиотеку», но один более правдоподобным:

for x, y in zip(range(0, width), range(0, height)): 
    picture.setPixel((x,y), Black)) 

Это вид работы, но линия не будет идеальным, если изображение не было совершенно квадрат - иначе он будет пропускать пиксели в самом широком направлении изображения. Чтобы решить эту проблему, необходим более совершенный алгоритм - но это второе место, у вас есть реальный способ доступа к пикселям на изображении - например, с помощью библиотеки изображений Python (PIL или Pillow) или pygame или другой библиотеки.

+0

Im, использующий среду jython для студентов, изображение создается ранее, и да, очень медленно получить все пиксели. Да, я думал, что все будет черным, но с левой стороны сверху вниз будет толстая черная линия. – user2194374

+1

На самом деле JES (Jython Environmen for Students) дает вам «пиксельный объект» как возвращаемое значение 'getPixel' ... – MartinStettner

+0

Спасибо за разъяснение, что @MartinStettner - я бы никогда не догадался, что такая вещь будет по-настоящему. – jsbueno

4

Большинство графических библиотек имеют какой-либо способ прямой линии.

В JES есть addLine функции, так что вы могли бы сделать

addLine(picture, 0, 0, width, height) 

Если вы застряли с установкой отдельных пикселей, вы должны взглянуть на Bresenham Line Algorithm, который является одним из наиболее эффективных алгоритмов для рисовать линии.

записку к коду: Что вы делаете с двумя вложенными циклами является следующей

for each column in the picture 
    for each row in the current column 
    set the pixel in the current column and current row to black 

поэтому в основном Youre заполняя все изображение с черными пикселями.

EDIT

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

width = getWidth(picture) 
height = getHeight(picture) 
space = 10 
for x in range(0, 2*width, space): 
    addLine(picture, x, 0, x-width, height) 

Это дает вам изображение, как (пример ручной тяге ...)

diagonal lines

Это делает использование clipping функциональность, предоставляемая большинством графических библиотек, то есть части строки, которые не находятся в изображении, просто игнорируются. Обратите внимание, что без 2*width (т.е.если x идет только до with), только верхняя левая половина линий будет обращена ...

+0

Я использовал addLine, но затем понял, что мне нужно, чтобы оно было на всем изображении. – user2194374

+0

И что случилось с линией, созданной 'addLine'? Если вы используете (0,0) и (widht, height) в качестве конечных точек для линии, все равно должно быть по всему изображению ... – MartinStettner

+0

Yep кроме этого только делает толстую черную линию высотой изображения в слева от картинки. Я могу добавить шаг в диапазон, который распространяется на линии, но я не уверен, как сделать их диагональными. – user2194374

1

Я хотел бы добавить некоторые математические соображения к обсуждению ...

(Просто потому, что это грустно, что функция AddLine JES черпает толькочерные линии и весьма ограничено ...)

Примечание: следующий код использует Bresenham по линии Алгоритм POIN выдан MartinStettner (так спасибо ему).

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

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

Код:

# The following is fast implementation and contains side effects... 

import random 

# Draw point, with check if the point is in the image area 
def drawPoint(pic, col, x, y): 
    if (x >= 0) and (x < getWidth(pic)) and (y >= 0) and (y < getHeight(pic)): 
    px = getPixel(pic, x, y) 
    setColor(px, col) 


# Draw line segment, given two points 
# From Bresenham's line algorithm 
# http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm 
def drawLine(pic, col, x0, y0, x1, y1): 

    dx = abs(x1-x0) 
    dy = abs(y1-y0) 
    sx = sy = 0 

    #sx = 1 if x0 < x1 else -1 
    #sy = 1 if y0 < y1 else -1 

    if (x0 < x1): 
    sx = 1 
    else: 
    sx = -1 
    if (y0 < y1): 
    sy = 1 
    else: 
    sy = -1 

    err = dx - dy 

    while (True): 

    drawPoint(pic, col, x0, y0) 

    if (x0 == x1) and (y0 == y1): 
     break 

    e2 = 2 * err 
    if (e2 > -dy): 
     err = err - dy 
     x0 = x0 + sx 

    if (x0 == x1) and (y0 == y1): 
     drawPoint(pic, col, x0, y0) 
     break 

    if (e2 < dx): 
     err = err + dx 
     y0 = y0 + sy 


# Draw infinite line from segment 
def drawInfiniteLine(pic, col, x0, y0, x1, y1): 
    # y = m * x + b 
    m = (y0-y1)/(x0-x1) 
    # y0 = m * x0 + b => b = y0 - m * x0 
    b = y0 - m * x0 

    x0 = 0 
    y0 = int(m*x0 + b) 
    # get a 2nd point far away from the 1st one 
    x1 = getWidth(pic) 
    y1 = int(m*x1 + b) 

    drawLine(pic, col, x0, y0, x1, y1) 


# Draw infinite line from origin point and angle 
# Angle 'theta' expressed in degres 
def drawInfiniteLineA(pic, col, x, y, theta): 

    # y = m * x + b 
    dx = y * tan(theta * pi/180.0) # (need radians) 
    dy = y 

    if (dx == 0): 
    dx += 0.000000001 # Avoid to divide by zero 

    m = dy/dx 

    # y = m * x + b => b = y - m * x 
    b = y - m * x 

    # get a 2nd point far away from the 1st one 
    x1 = 2 * getWidth(pic) 
    y1 = m*x1 + b 

    drawInfiniteLine(pic, col, x, y, x1, y1) 


# Draw multiple parallele lines, given offset and angle 
def multiLines(pic, col, offset, theta, randOffset = 0): 
    # Range is [-2*width, 2*width] to cover the whole surface 
    for i in xrange(-2*getWidth(pic), 2*getWidth(pic), offset): 
     drawInfiniteLineA(pic, col, i + random.randint(0, randOffset), 1, theta) 

# Draw multiple lines, given offset, angle and angle offset 
def multiLinesA(pic, col, offsetX, offsetY, theta, offsetA): 
    j = 0 
    # Range is [-2*width, 2*width] to cover the whole surface 
    for i in xrange(-2*getWidth(pic), 2*getWidth(pic), offsetX): 
     drawInfiniteLineA(pic, col, i, j, theta) 
     j += offsetY 
     theta += offsetA 



file = pickAFile() 
picture = makePicture(file) 
color = makeColor(0, 65, 65) #pickAColor() 
#drawline(picture, color, 10, 10, 100, 100) 
#drawInfiniteLine(picture, color, 10, 10, 100, 100) 
#drawInfiniteLineA(picture, color, 50, 50, 135.0) 
#multiLines(picture, color, 20, 56.0) 
#multiLines(picture, color, 10, 56.0, 15) 
multiLinesA(picture, color, 10, 2, 1.0, 1.7) 

show(picture) 


Выход (Картина Пьер Сулаж):


enter image description here

enter image description here

enter image description here


Надежда это дало некоторую забаву и идеи студентов JES ... А для других, а также ...

+0

@everyone Один важный побочный эффект появляется, когда 'm', в начале' drawInfiniteLine() ', имеет тенденцию быть бесконечным (float overflow). Этого можно избежать, например: 'if (abs (m)> 100.0): m = 100.0' сразу после вычисления' m' ... –

+0

Я не редактирую этот ответ еще раз, но это * * FIX, о котором я говорю, можно увидеть здесь **: http://stackoverflow.com/a/17288511/1715716 –