4

この写真 ( http://tinypic.com/r/34il9hu/6 )の空の星の乱数 (m から n までの間) を作成する関数を書きたいと思います。星は、単一の白いピクセル、または隣接する 4 つの白いピクセルの正方形のいずれかでランダムに構成する必要があります。また、木の枝、月、または鳥の上に (1 ピクセルの) 「星」を配置したくありません。けれど

Pythonでこれを行うにはどうすればよいですか? 誰でも助けることができますか?ありがとう!

私はこれまでのところこれを持っています:

私はこれを始めてこれまでに出てきましたが、それが正しいかどうか、または正しい軌道に乗っているかどうかさえわかりません:

def randomStars(small, large):
   import random
   file = pickAFile()
   pic = makePicture(myPic)
   #x = random.randrange(getWidth(pic))
   #y = random.randrange(getHeight(pic))
   for pixel in pic.getAllPixels():
      if random.random() < 0.25:
         pixel.red = random.randint(256)
         pixel.green = random.randint(256)
         pixel.blue = random.randint(256) 
   show(pic)

私は自分が何をしているのかわかりません:(

4

3 に答える 3

5

これは、skimageによって実装されているように、スーパーピクセルを試す良い例のようです。おそらく、問題に対してより簡単な方法でこれを行うことができます。

import urllib
import random
import io
import matplotlib.pyplot as plt
import skimage.segmentation
import pandas

# Read the image
f = io.BytesIO(urllib.urlopen('http://oi46.tinypic.com/34il9hu.jpg').read())
img = plt.imread(f, format='jpg')

# Prefer to keep pixels together based on location
# But not too much, so we still get some branches.
superpixel = skimage.segmentation.slic(img, n_segments=200, ratio=20)
plt.imshow(superpixel%7, cmap='Set2')

スーパーピクセル

スーパーピクセルができたので、スーパーピクセルごとに分類を行うことで、分類を少し簡単に行うことができます。ここで凝った分類を使用することもできますが、この例は非常に単純です。青みがかった空です。手動で行いましょう。

# Create a data frame with the relative blueish of every super pixel

# Convert image to hsv 
hsv = matplotlib.colors.rgb_to_hsv(img.astype('float32')/255)
# Define blueish as the percentage of pixels in the blueish range of the hue space
df =pandas.DataFrame({'superpixel':superpixel.ravel(), 
    'blue':((hsv[:,:,0] > 0.4) & (hsv[:,:,0]<0.8)).astype('float32').ravel(), 
    'value':hsv[:,:,2].ravel()})    
grouped = df.groupby('superpixel').mean()    
# Lookup the superpixels with the least blue
blue = grouped.sort('blue', ascending=True).head(100)
# Lookup the darkest pixels
light = grouped.sort('value', ascending=True).head(50)

# If superpixels are too dark or too blue, get rid of them
mask = (np.in1d(superpixel, light.index ).reshape(superpixel.shape) | 
    np.in1d(superpixel, blue.index ).reshape(superpixel.shape))

# Now we can put the stars on the blueish, not too darkish areas
def randomstar(img, mask):
    """random located star"""
    x,y = random.randint(1,img.shape[0]-1), random.randint(1,img.shape[1]-1)
    if not mask[x-1:x+1, y-1:y+1].any():
        # color not so random
        img[x,y,:] = 255
        img[x-1,y,:] = 255
        img[x+1,y,:] = 255
        img[x,y-1,:] = 255
        img[x,y+1,:] = 255

for i in range(100):
    randomstar(img, mask)
plt.imshow(img)

空の星

于 2013-02-28T22:25:35.853 に答える
3

Pythonの標準ライブラリには、強力で十分な画像操作コードは付属していませんが、インストールと使用が簡単な代替手段がいくつかあります。PILを使用してこれを行う方法を示します。

from PIL import Image

def randomStars(small, large):
    import random
    filename = pickAFile()
    pic = Image.open(filename)
    max_x, max_y = pic.size
    pixels = im.load()
    x = random.randrange(max_x)
    y = random.randrange(max_y)
    for i in range(max_x):
        for j in range(max_y):
            if random.random() < 0.25:
                red = random.randint(256)
                green = random.randint(256)
                blue = random.randint(256) 
                pixels[i, j] = (red, green, blue, 1)
    im.show()

このshow関数はアプリに画像を表示しません(そのためには、tkinterまたはのようなイベントループを備えたある種のGUIが必要ですPySide)。ファイルを一時ディレクトリに保存し、プレビューやxvなどのプラットフォーム固有のプログラムを実行して表示します。

あなたもファイルを保存したいと思うでしょう。それも簡単です:

    name, ext = os.path.splitext(filename)
    outfilename = '{}-with-stars.{}'.format(name, ext)
    im.save(outfilename)

これにより、デフォルトのJPEG設定で.jpgに保存され、ファイル名から必要なものを推測するPILに依存します。(つまり、はい、を使用するだけでPNGとして保存できます'{}-with-stars.png'.format(name)。)より詳細な制御が必要な場合は、明示的な形式と形式固有のオプションを指定して、PILでもそれを実行できます。


これまでのところ、これは既存のコードを機能するものに変換する方法であり、それを試してデバッグを開始できます。それは実際には元の問題に答えるものではありません。

この写真の空にランダムな数(mからnまで)の星を作成する関数を書きたい

したがって、最初に、すべてのピクセルにわたるループではなく、ループとしてこれが必要です。

for _ in random.randint(m, n):

今:

星は、単一の白いピクセル、または4つの隣接する白いピクセルの正方形のいずれかでランダムに構成される必要があります。

    x, y = random.randrange(max_x), random.randrange(max_y)
    if random.random() < .5:
        # draw white pixel at [x, y]
        pixels[x, y] = (1, 1, 1, 1)
    else:
        # draw square at [x, y], making sure to handle edges

また、木の枝、月、鳥の上に「星」(1ピクセル)を配置したくありません。

木の枝、月、または鳥の一部をどのように知るかを定義する必要があります。ピクセルの色でそれを定義できますか?

一見すると、できるかもしれません。月のピクセルはすべて、他のどのピクセルよりも明るく、飽和度が高く、赤に偏っています(さらに明るいコーナーのAPロゴを除く)。鳥と枝は何よりも暗いです。実際、それらは非常に明確であるため、おそらく正しい色空間計算を行うことを心配する必要はありません。それはこのようなもののように単純かもしれません:

r, g, b, a = pixels[x, y]
fake_brightness = r+g+b+a
if fake_brightness < 0.2:
    # Tree or bird, pick a new random position
elif 1.2 < fake_brightness < 2.8:
    # Moon, pick a new random position
else:
    # Sky or API logo, scribble away

(これらの数値は明らかに薄い空気から引き出されたものですが、少し試行錯誤することで使用可能な値が得られるはずです。)

もちろん、これを学習演習として行う場合は、この画像が非常に単純に解析可能であることに依存するのではなく、正しい色空間の計算を学習し、エッジ検出アルゴリズムを作成することもできます。

于 2013-02-28T20:34:21.963 に答える
1

次のようなアプローチを試してください。

for n in xrange(number_of_stars):
    # Find a good position
    while True:
        x, y = random_coords_in_image()
        if is_sky(image, x, y):
            break

    # paint a star there
    c = star_colour()

    if large_star():
        image.put(x, y, c)
        image.put(x, y+1, c)
        image.put(x+1, y+1, c)
        image.put(x+1, y, c)
    else:
        image.put(x, y, c)

私が使用した関数はかなり自明です。is_sky特定の場所での画像の色のいくつかの条件の推定を実装できます。

于 2013-02-28T20:37:04.413 に答える