2010-04-06 7 views
3

아트 프로젝트의 경우, 내가 할 일 중 하나는 이미지를 특정 픽셀로 확대하는 것입니다. 나는 턱을 문질러서 진행하는 방법에 대한 조언을 듣고 싶습니다.이미지를 픽셀 단위로 확대

Screen: 
sw - screen width 
sh - screen height 

Image: 
iw - image width 
ih - image height 

Pixel: 
px - x position of pixel in image 
py - y position of pixel in image 

Zoom: 
zf - zoom factor (0.0 to 1.0) 

Background colour: 
bc - background colour to use when screen and image aspect ratios are different 

출력을 : : 여기

는 입력 매개 변수입니다 내가 가진

The zoomed image (no anti-aliasing) 
The screen position/dimensions of the pixel we are zooming to. 

When zf is 0 the image must fit the screen with correct aspect ratio. 
When zf is 1 the selected pixel fits the screen with correct aspect ratio. 

하나의 아이디어가 POVRAY 같은 것을 사용하고 큰 이미지 질감 또는 일부 도서관으로 카메라를 이동하는 것이 었습니다 (예 : 파이 게임). 누구든지 간단한 의사 코드로 더 영리한 것을 생각해보십시오.

더 간단하게 유지하려면 이미지와 화면의 화면 비율을 같게 만들 수 있습니다. 나는 그걸로 살 수있다.

필요에 따라 추가 정보로 업데이트하겠습니다. PHP에

UPDATE

변환 허용 대답

Image Pixel Zoom on GitHub

+0

일련의 확대/축소 수준을 통해 최종 이미지 또는 애니메이션을 원한다면 먼저 명확히 할 수 있습니까? 애니메이션이 필요한 경우 최대 및 최소 줌 레벨 (0 및 1)을 설명 할 필요가있을뿐만 아니라 카메라가 이동하는 속도가 선형인지 아닌지 (선형이 약간 부자연스럽고 가속되어 즉시 멈 춥니 다). 또한 카메라가 확대/축소되는 픽셀은 일반적으로 중앙에 있지 않으므로 확대/축소가 진행되는 것이 아니라 카메라를 번역하여 픽셀을 넘기는 것입니다. 이것은 선형이라고 가정 할 수 있지만 확인은 좋을 것입니다. – Unreason

+0

메모 - 알고리즘은 간단하지만 기존 라이브러리를 더 똑똑하게 사용하여 호출하는 것이 좋습니다. – Unreason

+0

주어진 줌 요소에 대해 나는 단지 하나의 이미지 프레임만을 원한다. 그 다음에는 줌 요소 0에서 1까지 단계별로 애니메이션을 만듭니다. 속도는 정의하기가 더 어렵습니다. 고정 된 단계로 0에서 1 줌 배율로 이동하면 픽셀에 대해 "자연스러운"모션을 찾고 있습니다 (고정 할 필요는 없지만 훌륭합니다). 또한 기존 라이브러리를 사용해도 괜찮습니다. – zaf

답변

4

원본 이미지의 컬러 값은 윈도우 사이즈/화상 사이즈에 대해서 배열

image[x][y] 

이어서 확대 된 이미지의 컬러 값은

image[x+zf*(px-x)][y+zf*(py-y)] 

로 주어지면 -주의해야 화상의 초기 준비 창에 더 이상 맞지 않는 지점까지 이미지를 확대하고 나머지 픽셀을 원하는 배경색으로 채 웁니다. 파이썬에서

당신이

import Image 

편집에서 개체와

im = Image.open("filename.ext") 

을 설정 한 후

def naivezoom(im, px, py, zf, bg): 
    out = Image.new(im.mode, im.size)   
    pix = out.load() 
    iw, ih = im.size 
    for x in range(iw): 
     for y in range(ih): 
      xorg = x + zf*(px - x) 
      yorg = y + zf*(py - y) 
      if xorg >= 0 and xorg < iw and yorg >= 0 and yorg < ih: 
       pix[x,y] = im.getpixel((xorg , yorg)) 
      else: 
       pix[x,y] = bg 
    return out 

처럼 뭔가를 할 수 있습니다 감안할 때 유래 로고 당신은 얻을 것이다

,691

이미지 코드 다음

#!/bin/env python 
from Tkinter import * 
import Image 
import ImageTk 

def naivezoom(im, p, zf, bg): 
    out = Image.new(im.mode, im.size) 
    pix = out.load() 
    iw, ih = im.size 
    for x in range(iw): 
     for y in range(ih): 
      xorg = x + zf*(p[0] - x) 
      yorg = y + zf*(p[1] - y) 
      if xorg >= 0 and xorg < iw and yorg >= 0 and yorg < ih: 
       pix[x,y] = im.getpixel((xorg , yorg)) 
      else: 
       pix[x,y] = bg 
    return out 

class NaiveTkZoom: 
    def __init__(self, parent=None): 
     root = Tk() 
     self.im = Image.open('logo.jpg') 
     self.zf = 0.0 
     self.deltazf = 0.02 
     self.p = (0.1*self.im.size[0],0.1*self.im.size[1]) 
     self.bg = 255 
     canvas = Canvas(root, width=self.im.size[0]+20 , height=self.im.size[1]+20) 
     canvas.pack() 
     root.bind('<Key>', self.onKey) 
     self.canvas = canvas 
     self.photo = ImageTk.PhotoImage(self.im) 
     self.item = self.canvas.create_image(10, 10, anchor=NW, image=self.photo) 
    def onKey(self, event): 
     if event.char == "+": 
      if self.zf < 1: 
       self.zf += self.deltazf 
     elif event.char == "-": 
      if self.zf > 0: 
       self.zf -= self.deltazf 
     self.out = naivezoom(self.im, self.p, self.zf, self.bg) 
     self.photo = ImageTk.PhotoImage(self.out) 
     self.canvas.delete(self.item) 
     self.item = self.canvas.create_image(10, 10, anchor=NW, image=self.photo) 
     print self.p, self.zf 

if __name__ == "__main__": 
    NaiveTkZoom() 
    mainloop() 
얻어졌다 동일한 지점 주위 ZF = 0.96 대 25,6

alt text http://i41.tinypic.com/24g5848.png

지점 주위 ZF = 0.3 대 363,210

alt text http://i40.tinypic.com/i1cwg7.jpg

,

사용되는 라이브러리와 픽셀 별 접근 방식은 세계에서 가장 빠르지 않지만 g 당신과 함께 놀 수있는 충분한 재료를 줘보십시오.

위의 코드는 매우 깨끗하지 않습니다.

EDIT2 (and3, 공식을 중심으로 함) : 다른 시도가 있는데 번역이 추가되었지만 이것이 최종적인 것이 아니라고 생각합니다. (수식을 확인할 시간이 없습니다). 또한 번역 속도가 일정하지만 속도가 느려지 고 배경이 표시 될 수 있습니다 (확대 점이 가장자리에 너무 가까울 경우).
원본 이미지에 페인트 할 필요없이 원본 이미지의 점을 볼 수 있도록 원래 이미지에 점을 추가했습니다.

#!/bin/env python 
from Tkinter import * 
import Image 
import ImageTk 

def markImage(im, p, bg): 
    pix = im.load() 
    pix[ p[0], p[1] ] = bg 

def naiveZoom(im, p, zf, bg): 
    out = Image.new(im.mode, im.size) 
    pix = out.load() 
    iw, ih = im.size 
    for x in range(iw): 
     for y in range(ih): 
      xorg = x + zf*(p[0]+0.5-x) + zf*(1-zf)*(p[0]-iw/2) 
      yorg = y + zf*(p[1]+0.5-y) + zf*(1-zf)*(p[1]-ih/2) 
      if xorg >= 0 and xorg < iw and yorg >= 0 and yorg < ih: 
       pix[x,y] = im.getpixel((xorg , yorg)) 
      else: 
       pix[x,y] = bg 
    return out 

class NaiveTkZoom: 
    def __init__(self, parent=None): 
     root = Tk() 
     self.im = Image.open('py.jpg') 
     self.zf = 0.0 
     self.deltazf = 0.05 
     self.p = (round(0.3*self.im.size[0]), round(0.3*self.im.size[1])) 
     self.bg = 255 
     markImage(self.im, self.p, self.bg) 
     canvas = Canvas(root, width=self.im.size[0]+20 , height=self.im.size[1]+20) 
     canvas.pack() 
     root.bind('<Key>', self.onKey) 
     self.canvas = canvas 
     self.photo = ImageTk.PhotoImage(self.im) 
     self.item = self.canvas.create_image(10, 10, anchor=NW, image=self.photo) 
     self.change = False 
    def onKey(self, event): 
     if event.char == "+": 
      if self.zf < 1: 
       self.zf += self.deltazf 
       self.change = True 
     elif event.char == "-": 
      if self.zf > 0: 
       self.zf -= self.deltazf 
       self.change = True 
     if self.change: 
      self.out = naiveZoom(self.im, self.p, self.zf, self.bg) 
      self.photo = ImageTk.PhotoImage(self.out) 
      self.canvas.delete(self.item) 
      self.change = False 
     self.item = self.canvas.create_image(10, 10, anchor=NW, image=self.photo) 
     print self.p, self.zf 

if __name__ == "__main__": 
    NaiveTkZoom() 
    mainloop() 

개선 할 수있는 항목이 상당히 많습니다. :)

+0

니스! 방정식과 샘플 코드를 보내 주셔서 감사합니다. 한가지 주목할 점은 선택한 픽셀이 왼쪽 위 구석의 어딘가에 있으면 확대 할 때 왼쪽 상단 구석에 포옹된다는 것입니다. 대신에 확대 할 때 선택한 픽셀을 중심으로 찾고 있습니다 . – zaf

+0

대답을 업데이트했습니다. 여기서 포옹을하는 것은 아닙니다. 주어진 수식을 올바르게 적용하고 있습니까? – Unreason

+0

업데이트 된 코드를 보내 주셔서 감사합니다. 나는 +/- 키 터치를 정말 좋아했습니다! 확인 - 이미지의 빨간색 (또는 모든 색상 표식) 픽셀로 이미지를 시도한 다음 확대하면 선택한 픽셀의 왼쪽 상단이 그대로 유지됩니다. 우리가 원하는 것은 화면의 픽셀 중심 그 자체입니다. 300,300에 빨간색 픽셀이있는 1000x1000 이미지를 사용하고 있습니다. – zaf

0

편집 : 나는 그것을 할 Processing

:이 프레임 워크를 확인할 수 있습니다 예술 프로젝트의 1D, 시작 직접를 작성하여 제약으로 확대 된 이미지를 원본 이미지로 변환 :

당신이 선형 변환을 할 때, 그것은 형태 :

D (X) = AX + B

당신이 원하는 : Z = 0

: D (PX) = PX D (PX + 1) = PX + 1

Z = 1 : D (PX) = 0 D (PX + 1) = s

승이 제공 = 0, Z에 대한

A = 1, B = 0, D (x)는 Z = 1 = X

A = SW = B -sw. PX, D (X) = sw.x - 모든 Z 들어

, 당신은 이들의 선형 조합 사용 sw.px :

D (X) = Z를 (sw.x - sw.px)D (x) = (z.sw + 1-z) .x - z.sw.px

이제 역함수를 써서 출력에서 ​​원래 좌표를 얻습니다. 좌표

ID (XOUT) = (XOUT z.sw.px +)/- 당신의 출력 화상을 기입 할 수 있도록 (z.sw 1 + z)

입력 이미지.각 출력 픽셀의 값은 OriginalPixel [ID (xout)]입니다 (ID (xout)이 [0..sw]에없는 경우 배경 값 사용)

2D의 경우 아이디어는 비슷하지만 가로 세로 비는 조금 더 노력해야합니다.

+0

재미있는 1D에 대한 생각. 나는 방정식을 grok하려고하고 내가 그들 주위에 내 머리를 얻을 수 있는지보십시오. 그렇습니다. 나는 매우 멋지게 처리 했었습니다. 손으로 직접 할 수 없다면 사용할 첫 번째 도구 일 것입니다. – zaf

0

내가 원하는 것을 정확히 이해한다면. Gimp와 같은 그래픽 프로그램에서 이미지를 열면 줌 레벨을 1로 설정하고 스크린 샷을 찍을 수 있습니다. 그런 다음 줌 레벨을 높이고 스크린 샷을 다시 찍습니다. 그런 다음 mencoder를 사용하여 스크린 샷에서 AVI를 만듭니다.

+0

증분 스케일 수준 및 고정 된 자르기를 사용하여 imagemagic을 실행하는 스크립트를 작성할 수도 있습니다. 각 축척 된 이미지를 001.jpg 002.jpg ...와 같은 이름으로 저장하고 mencoder를 사용하여 다른 동영상을 만듭니다. – Ross

+0

방정식을 이해하지 못한다면 다른 도구를 자동화하는 방법을 살펴볼 것입니다. 그러나 제가 찾고있는 효과를주는 도구를 찾기 전에 새로운 도구를 사용해 봐야 할 것입니다. – zaf

관련 문제