画像処理(エフェクト)

 投稿者:山中和義  投稿日:2009年 4月20日(月)20時13分25秒
  ページめくり
OPTION ARITHMETIC NATIVE !CPUパワー

SET COLOR MODE "NATIVE"
GLOAD "c:\BASICw32\SAMPLE\ZENKOUJI.JPG" !画像を読み込む
ASK PIXEL SIZE (0,0; 1,1) w,h !画像の縦横の大きさ(ピクセル単位)を調べる
DIM p(w,h),q(w,h) !画像の大きさに対応する配列要素を用意する
ASK PIXEL ARRAY (0,1) p !画像の各点の色情報を配列に格納する
PRINT "画像の大きさ 縦:";h;" 横:";w
!SET BITMAP SIZE w,h !ウィンドウの大きさを画像に合わせる


LET R=30 !めくりの半径 ※
LET Dx=20 !めくりの量 ※
LET th=RAD(30) !めくりの方向 ※


DIM M1(3,3),M2(3,3),M4(3,3),M5(3,3),M7(3,3),M8(3,3)
MAT M1=IDN !画像の中央を原点へ
LET M1(1,3)=-w/2
LET M1(2,3)=-h/2

MAT M2=IDN !めくり方向をX軸に一致させ、半径を1とする
LET M2(1,1)=COS(th)/R
LET M2(1,2)=SIN(th)/R
LET M2(2,1)=-SIN(th)/R
LET M2(2,2)=COS(th)/R

MAT M4=IDN !めくりの中心を原点へ
LET M4(1,3)=-Dx/R

MAT M5=IDN !INV(M4)
LET M5(1,3)=Dx/R

MAT M7=IDN !INV(M2)
LET M7(1,1)=COS(th)*R
LET M7(1,2)=-SIN(th)*R
LET M7(2,1)=SIN(th)*R
LET M7(2,2)=COS(th)*R

MAT M8=IDN !INV(M1)
LET M8(1,3)=w/2
LET M8(2,3)=h/2


MAT q=ZER !黒色

!座標変換 f:(x,y)→(xx,yy)の逆変換を考える

!下側の部分
DIM t(3)
FOR yy=1 TO h !変換後の画素位置で走査する
   FOR xx=1 TO w

      LET t(1)=xx !非線形変換前の線形変換
      LET t(2)=yy
      LET t(3)=1

      MAT t=M1*t
      MAT t=M2*t
      MAT t=M4*t

      !非線形変換

      !横から見た図(効果のかかる方向をX軸方向にとる)
      !Z軸
      !↑
      !・→ X軸
      !      視線
      !       ↓
      !          x'=1
      !        ──・     上側
      !           \    ↑
      !  めくりの中心 → *  ・x'=0 --------
      !           /    ↓
      ! 画素面 ─────・     下側
      !          x'=-1
      !
      !・下側と上側の順に2回の描画で陰面消去を行う

      LET op=0 !計算誤差を避けるため元の値を使う
      SELECT CASE t(1) !x'=R*Sin(θz)
      CASE IS >=1
         LET op=-1 !NOP
      CASE IS >=0
         LET t(1)=ASIN(ABS(t(1))) !0≦R*ArcSin(x'/R)≦R*PI/2
         LET op=1 !変換された座標を使う
      CASE ELSE !x'
      END SELECT

      MAT t=M5*t !非線形変換後の線形変換
      MAT t=M7*t
      MAT t=M8*t
      !PRINT xx;yy !debug
      !MAT PRINT t;

      LET x=INT(t(1)) !元の画素での位置
      LET y=INT(t(2))

      SELECT CASE op !元の画素を読み込んで書き込む
      CASE 0
         LET q(xx,yy)=p(xx,yy)
      CASE 1
         IF x<1 OR x>w OR y<1 OR y>h THEN !範囲内なら
         ELSE
            LET q(xx,yy)=p(x,y)
         END IF
      CASE ELSE
      END SELECT

   NEXT xx
NEXT yy

!MAT PLOT CELLS, IN 0,1; 1,0 :q !画像を表示する debug
!STOP

!上側の部分(めくり上がって裏返る部分)
FOR yy=1 TO h !変換後の画素位置で走査する
   FOR xx=1 TO w

      LET t(1)=xx !非線形変換前の線形変換
      LET t(2)=yy
      LET t(3)=1

      MAT t=M1*t
      MAT t=M2*t
      MAT t=M4*t


      !非線形変換
      !!!●巻き込まない場合は、こちら
      LET op=0 !計算誤差を避けるため元の値を使う
      SELECT CASE t(1)
      CASE IS >=1
         LET op=-1 !NOP
      CASE IS >=0
         LET t(1)=PI-ASIN(ABS(t(1))) !R*PI/2≦R*PI-R*ArcSin(x'/R)≦R*PI
         LET op=1
      CASE ELSE
         LET t(1)=PI-t(1) !R*PI-x'
         LET op=1
      END SELECT

      !!!●巻き込む場合は、こちら
      !!!LET op=0 !計算誤差を避けるため元の値を使う
      !!!SELECT CASE t(1)
      !!!CASE IS >=1
      !!!   LET op=-1 !NOP
      !!!CASE IS >=0
      !!!   LET t(1)=PI-ASIN(ABS(t(1)))
      !!!   LET op=1
      !!!CASE IS >=-1
      !!!   LET t(1)=PI+ASIN(ABS(t(1)))
      !!!   LET op=1
      !!!CASE ELSE
      !!!   LET op=-1 !NOP
      !!!END SELECT


      MAT t=M5*t !非線形変換後の線形変換
      MAT t=M7*t
      MAT t=M8*t
      !PRINT xx;yy !debug
      !MAT PRINT t;

      LET x=INT(t(1)) !元の画素での位置
      LET y=INT(t(2))

      SELECT CASE op !元の画素を読み込んで書き込む
      CASE 0
         LET q(xx,yy)=p(xx,yy)
      CASE 1
         IF x<1 OR x>w OR y<1 OR y>h THEN !範囲内なら
         ELSE
            LET q(xx,yy)=p(x,y)
         END IF
      CASE ELSE
      END SELECT

   NEXT xx
NEXT yy

MAT PLOT CELLS, IN 0,1; 1,0 :q !画像を表示する

END
 

Re: 画像処理(エフェクト)

 投稿者:山中和義  投稿日:2009年 4月21日(火)10時30分2秒
  > No.337[元記事へ]

●球
OPTION ARITHMETIC NATIVE !CPUパワー

SET COLOR MODE "NATIVE"
GLOAD "c:\BASICw32\SAMPLE\ZENKOUJI.JPG" !画像を読み込む
ASK PIXEL SIZE (0,0; 1,1) w,h !画像の縦横の大きさ(ピクセル単位)を調べる
DIM p(w,h),q(w,h) !画像の大きさに対応する配列要素を用意する
ASK PIXEL ARRAY (0,1) p !画像の各点の色情報を配列に格納する
PRINT "画像の大きさ 縦:";h;" 横:";w
!SET BITMAP SIZE w,h !ウィンドウの大きさを画像に合わせる


LET Rx=100 !球の半径
LET Ry=100
LET Sx=150 !球の中心
LET Sy=150
LET Tx=w/2+50 !貼付け位置
LET Ty=h/2


DIM M1(3,3),M2(3,3),M3(3,3),M6(3,3),M7(3,3),M8(3,3)
MAT M1=IDN !中心の移動
LET M1(1,3)=-Sx
LET M1(2,3)=-Sy

MAT M2=IDN !比率の変換
LET M2(1,1)=1/Rx
LET M2(2,2)=1/Ry

MAT M7=IDN !INV(M2)
LET M7(1,1)=Rx
LET M7(2,2)=Ry

MAT M8=IDN !貼付け画像の移動
LET M8(1,3)=Tx
LET M8(2,3)=Ty


MAT q=ZER !黒色

!座標変換 f:(x,y)→(xx,yy)の逆変換を考える

DIM t(3)
FOR yy=1 TO h !変換後の画素位置で走査する
   FOR xx=1 TO w

      LET t(1)=xx !非線形変換前の線形変換
      LET t(2)=yy
      LET t(3)=1

      MAT t=M1*t
      MAT t=M2*t

      LET tt=SQR(t(1)*t(1)+t(2)*t(2)) !(x,y)に応じて回転する
      IF tt=0 THEN
         LET co=0
         LET si=0
      ELSE
         LET co=t(1)/tt
         LET si=t(2)/tt
      END IF

      MAT M3=IDN
      LET M3(1,1)=co !X軸上への写像
      LET M3(1,2)=si
      LET M3(2,1)=-si
      LET M3(2,2)=co

      MAT t=M3*t


      !非線形変換
      IF t(1)>=0 AND t(1)<1 THEN !球の内
         LET t(1)=ASIN(t(1)) !凸
         !LET t(1)=ATN(t(1))*1.5 !凹
         LET op=1 !変換された座標を使う
      ELSE !球の外
         LET op=0 !計算誤差を避けるため元の値を使う
      END IF


      SELECT CASE op !元の画素を読み込んで書き込む
      CASE 0
         LET q(xx,yy)=p(xx,yy)
      CASE 1
         MAT M6=IDN !INV(M3) !非線形変換後の線形変換
         LET M6(1,1)=co
         LET M6(1,2)=-si
         LET M6(2,1)=si
         LET M6(2,2)=co

         MAT t=M6*t
         MAT t=M7*t
         MAT t=M8*t
         !PRINT xx;yy !debug
         !MAT PRINT t;

         LET x=INT(t(1)) !元の画素での位置
         LET y=INT(t(2))

         IF x<1 OR x>w OR y<1 OR y>h THEN !範囲内なら
         ELSE
            LET q(xx,yy)=p(x,y)
         END IF
      CASE ELSE !NOP
      END SELECT

   NEXT xx
NEXT yy

MAT PLOT CELLS, IN 0,1; 1,0 :q !画像を表示する

END


●モザイク
OPTION ARITHMETIC NATIVE !CPUパワー

SET COLOR MODE "NATIVE"
GLOAD "c:\BASICw32\SAMPLE\ZENKOUJI.JPG" !画像を読み込む
ASK PIXEL SIZE (0,0; 1,1) w,h !画像の縦横の大きさ(ピクセル単位)を調べる
DIM p(w,h),q(w,h) !画像の大きさに対応する配列要素を用意する
ASK PIXEL ARRAY (0,1) p !画像の各点の色情報を配列に格納する
PRINT "画像の大きさ 縦:";h;" 横:";w
!SET BITMAP SIZE w,h !ウィンドウの大きさを画像に合わせる


LET Rx=10 !1辺の長さ
LET Ry=10
LET th=RAD(30) !方向


DIM M1(3,3),M2(3,3),M7(3,3),M8(3,3)
MAT M1=IDN !画像の中央を原点へ
LET M1(1,3)=-w/2
LET M1(2,3)=-h/2

MAT M2=IDN !方向をX軸に一致させ、半径を1とする
LET M2(1,1)=COS(th)/Rx
LET M2(1,2)=SIN(th)/Rx
LET M2(2,1)=-SIN(th)/Ry
LET M2(2,2)=COS(th)/Ry

MAT M7=IDN !INV(M2)
LET M7(1,1)=COS(th)*Rx
LET M7(1,2)=-SIN(th)*Rx
LET M7(2,1)=SIN(th)*Ry
LET M7(2,2)=COS(th)*Ry

MAT M8=IDN !INV(M1)
LET M8(1,3)=w/2
LET M8(2,3)=h/2


MAT q=ZER !黒色

!座標変換 f:(x,y)→(xx,yy)の逆変換を考える

DIM t(3)
FOR yy=1 TO h !変換後の画素位置で走査する
   FOR xx=1 TO w

      LET t(1)=xx !非線形変換前の線形変換
      LET t(2)=yy
      LET t(3)=1

      MAT t=M1*t
      MAT t=M2*t

      !非線形変換
      LET t(1)=INT(t(1))+0.5
      LET t(2)=INT(t(2))+0.5

      MAT t=M7*t !非線形変換後の線形変換
      MAT t=M8*t
      !PRINT xx;yy !debug
      !MAT PRINT t;

      LET x=INT(t(1)) !元の画素での位置
      LET y=INT(t(2))

      IF x<1 OR x>w OR y<1 OR y>h THEN !範囲内なら
      ELSE
         LET q(xx,yy)=p(x,y)
      END IF

   NEXT xx
NEXT yy

MAT PLOT CELLS, IN 0,1; 1,0 :q !画像を表示する

END
 

戻る