2

こんにちは、画像の右上から左下に対角線を引こうとしているのは、これまでのところ私のコードです。

  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)

ありがとう

4

3 に答える 3

4

ほとんどのグラフィック ライブラリには、線を直接描画する何らかの方法があります。

JESには関数addLineがあるので、あなたはすることができます

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

単一ピクセルの設定に行き詰まっている場合は、線を描画するための最も効率的なアルゴリズムの 1 つであるBresenham Line Algorithmを確認する必要があります。

コードへの注意: ネストされた 2 つのループで行っていることは次のとおりです。

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

基本的に、画像全体を黒いピクセルで塗りつぶします。

編集

画像全体に複数の対角線を描く (その間にスペースを残す) には、次のループを使用できます。

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

これにより、次のようなイメージが得られます(例は手描きです...)

対角線

これは、ほとんどのグラフィックス ライブラリが提供するクリッピング機能を利用します。つまり、画像内にない線の部分は単純に無視されます。なしで2*width(つまり、xまでしか上がらない場合with)、線の左上半分だけが描画されることに注意してください...

于 2013-03-23T09:52:37.463 に答える
2

議論にいくつかの数学的な考慮事項を追加したいと思います...

(JES の addLine 関数が黒線しか描画できず、かなり制限されているのは悲しいからです...)

注 :次のコードは、(彼に感謝します)によって指摘されたBresenham の Line Algorithmを使用しています。MartinStettner

Bresenham のライン アルゴリズムは、与えられた 2 点間の直線に近い近似を形成する次数を決定するアルゴリズムです。ピクセルはアトミック エンティティであるため、線は何らかの近似を使用してコンピュータ画面上でのみ描画できます。

注 : 次のコードを理解するには、学校での数学の基本コース (直線の方程式と三角法) を少し覚えておく必要があります。

コード :

# 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)


出力 ( Pierre Soulagesによる絵画) :


ここに画像の説明を入力

ここに画像の説明を入力

ここに画像の説明を入力


これがJESの生徒たちに楽しみとアイデアを与えてくれることを願っています...そして他の人たちにも...

于 2013-06-27T02:04:59.713 に答える
1

pictureあなたのオブジェクトはどこ から来たのですか?それは何ですか?これまでのところ機能していないものは何ですか? また、使用しようとしている画像アクセス用のライブラリは何ですか? (つまり、「getWidth、getHeight、getPixel、setColor) をどこから取得するか、または取得するつもりですか?

setColor 呼び出しで使用できるオブジェクト全体として「ピクセル」を提供するライブラリは存在しないと思います。存在する場合、世界で最も遅いものになるでしょう-おそらく銀河で。

一方、これらのメソッドが存在し、Picture があった場合、上記のコードはすべての画像を黒でカバーします。すべての可能な "y" 値 (0 から高さまで) をすべての可能な x 値 (0 から幅まで) 内に取得しています。 )、それぞれの黒を着色します。

線を引くには、次のように x と y を同時に変更する必要があります。

(別の「架空のライブラリ」を使用していますが、もう1つもっともらしい:

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

これはある程度機能しますが、画像が完全に正方形でない限り、線は完全ではありません。そうでない場合、画像の最も広い方向のピクセルをスキップします。それを解決するには、より洗練されたアルゴリズムが必要ですが、Python の Imaging Library (PIL または Pillow)、pygame、またはその他のライブラリを使用するなど、画像上のピクセルに実際にアクセスする方法は 2 番目です。

于 2013-03-23T09:51:05.230 に答える