説明
画像の減色と背景色を透明化するクロマキーを行うためのモジュール。//デバッグモード #define global DEBUGxDEBUG 0 #include "hspcv.as" #module #uselib "crtdll.dll" #func time "time" sptr #defcfunc timer local s1 time varptr(s1) return s1 #deffunc delog str _str getkey key, 13 if key : return dialog ""+_str getkey key, 16 if key : wait 1 : end return #global //画像をピクセルデータに変換 #module PixelData m_x, m_y, m_width, m_height, m_pd, m_pR, m_pG, m_pB, m_rect, m_pdm, m_filter, m_hspwinid, m_ifMoveCheck, m_ifMoveCheck2, m_ifPixelData, m_HeightCount, m_WidthCount, m_ifChromakey, m_ifChromakeyColor, m_ifChromakeyBackGround, m_pdc, m_pdt, m_ifSoftChromakey #define R m_pd(xcnt, ycnt, 0) //色情報R #define G m_pd(xcnt, ycnt, 1) //色情報B #define B m_pd(xcnt, ycnt, 2) //色情報B #define P m_pd(xcnt, ycnt, 3) //減色パレットID #define C m_pd(xcnt, ycnt, 4) //透明色フラグ #define pR m_pR(cnt) #define pG m_pG(cnt) #define pB m_pB(cnt) #define tR tR_(cnt) #define tG tG_(cnt) #define tB tB_(cnt) #define tC tC_(cnt) #define th threshold #define mR m_pdm(xcnt, ycnt, 0) #define mG m_pdm(xcnt, ycnt, 1) #define mB m_pdm(xcnt, ycnt, 2) #define mP m_pdm(xcnt, ycnt, 3) #define cR m_pdc(xcnt, ycnt, 0) #define cG m_pdc(xcnt, ycnt, 1) #define cB m_pdc(xcnt, ycnt, 2) #define sR m_pdcc(xcnt, ycnt, 0) #define sG m_pdcc(xcnt, ycnt, 1) #define sB m_pdcc(xcnt, ycnt, 2) //初期化を行う //newmod モジュール変数, HSPのウィンドウID, 画像を取得する位置X, 取得する画像の横の長さ, 取得する画像の縦の長さ, 動体検知を使用するかどうかのフラグ, クロマキーを利用するかどうかのフラグ, ソフトクロマキーを使用するかどうかのフラグ #modinit int _hspwinid, int _x, int _y, int _width, int _height, int _ifMoveCheck, int _ifChromakey, int _ifSoftChromakey m_width = _width m_height = _height m_x = _x m_y = _y m_hspwinid = _hspwinid dim m_pd, m_width, m_height, 5 if _ifMoveCheck { dim m_pdm, m_width, m_height, 4 m_ifMoveCheck = 1 } if _ifChromakey { m_ifChromakey = _ifChromakey dim m_pdc, _width, _height, 3 } if _ifSoftChromakey{ m_ifSoftChromakey = _ifSoftChromakey dim m_pdcc, _width, _height, 3 } dim m_pR, 1 dim m_pG, 1 dim m_pB, 1 return //内部で使用する画像のピクセルデータを取得する //mod_PixelData_Get モジュール変数, 取得する画像の間隔 #modfunc mod_PixelData_Get int _rect, local s1, local xcnt, local ycnt m_ifPixelData = 1 if _rect == 0 : m_rect = 1 : else : m_rect = _rect m_WidthCount = m_width / m_rect m_HeightCount = m_height / m_rect s1 = ginfo_sel gsel m_hspwinid //配列変数に画像の色データを入れる repeat m_HeightCount ycnt = cnt * m_rect repeat m_WidthCount xcnt = cnt * m_rect pget xcnt, ycnt R = ginfo_r G = ginfo_g B = ginfo_b loop loop gsel s1 return //画像にフィルタをかける //mod_PixelData_Filter モジュール変数, フィルタの種類, 閾値, 精度を増すために繰り返し処理を行う回数 #modfunc mod_PixelData_Filter int _filter, int _threshold, int _precision, local s1, local s2, local s3, local xcnt, local ycnt, local threshold if m_ifPixelData == 0 :return if _threshold == 0 : threshold = 1 : else : threshold = _threshold if _precision == 0 : precision = 1 : else : precision = _precision if _filter == 0 : m_filter = 1 : else : m_filter = _filter switch m_filter case 1 //減色フィルタ //パターンの検索 repeat precision //精度を増すために繰り返し実行させる repeat m_HeightCount ycnt = cnt * m_rect repeat m_WidthCount xcnt = cnt * m_rect hit = 0 s2 = length(m_pR) repeat s2 if pR-th<=R{ if pR+th>=R{ if pG-th<=G{ if pG+th>=G{ if pB-th<=B{ if pB+th>=B{ tR += R tG += G tB += B tC++ pR = tR / tC pG = tG / tC pB = tB / tC P = cnt hit = 1 //デバッグ///////////// #if DEBUGxDEBUG gsel 0 color pR, pG, pB boxf P*5, 0, P*5+5, 5 pos P*5, 12*tC+10 : mes ""+tC wait 0 #endif /////////////////////// break } } } } } } loop //閾値から外れた色だった場合 if hit == 0{ tR_(s2) = R tG_(s2) = G tB_(s2) = B m_pR(s2) = R m_pG(s2) = G m_pB(s2) = B tC_(s2) = 1 P = s2 //デバッグ///////////// #if DEBUGxDEBUG gsel 0 color R, G, B boxf s2*5, 0, s2*5+5, 5 pos s2*5, 22 : mes "1" wait 0 #endif /////////////////////// } loop loop loop swbreak swend return //画像を描画する //mod_PixelData_Draw モジュール変数 //フィルタが使用されていない場合そのままのピクセルデータが描画される #modfunc mod_PixelData_Draw local s1, local s2, local xcnt, local ycnt if m_ifPixelData == 0 :return s1 = ginfo_cx : s2 = ginfo_cy repeat m_HeightCount ycnt = cnt * m_rect repeat m_WidthCount xcnt = cnt * m_rect switch m_filter case 0 color R, G, B swbreak case 1 color m_pR(P), m_pG(P), m_pB(P) swbreak swend if m_rect <= 1{ pset s1 + xcnt, s2 + ycnt }else{ boxf s1 + xcnt, s2 + ycnt, s1 + xcnt + m_rect, s2 + ycnt + m_rect } loop loop return #modfunc mod_PixelData_MoveCheck_init dim m_pdm, m_width, m_height, 3 return //動体検知 //mod_PixelData_MoveCheck モジュール変数, 閾値, mod_PixelData_MoveDrawを使用するかどうかのフラグ #modfunc mod_PixelData_MoveCheck var _var, int _threshold, int _ifMoveDraw, local s1, local xcnt, local ycnt, local threshold if m_ifPixelData == 0 : return if m_ifMoveCheck == 0 : return threshold = _threshold repeat m_HeightCount ycnt =cnt * m_rect repeat m_WidthCount xcnt =cnt * m_rect if _ifMoveDraw { if mP { mP = 0 } } switch m_filter case 0 if m_ifMoveCheck2 { if (mR+th>=R)|(mR+th<=R) { if (mG-th>=G)|(mG+th<=G) { if (mB-th>=B)|(mB+th<=B) { s1++ if _ifMoveDraw{ mP = 1 } } } } } mR = R mG = G mB = B swbreak case 1 if m_ifMoveCheck2 = 1 { if (mR-th>=m_pR(P))|(mR+th<=m_pR(P)) { if (mG-th>=m_pG(P))|(mG+th<=m_pG(P)) { if (mB-th>=m_pB(P))|(mB+th<=m_pB(P)) { s1++ if _ifMoveDraw{ mP = 1 } } } } } mR = m_pR(P) mG = m_pG(P) mB = m_pB(P) swbreak swend loop loop if m_ifMoveCheck2 == 1{ _var = s1 }else{ m_ifMoveCheck2 = 1 _var = 0 } return //動体検知部位の描画を行う //mod_PixelData_MoveDraw モジュール変数 #modfunc mod_PixelData_MoveDraw local s1, local s2, local xcnt, local ycnt if m_ifPixelData == 0 : return if m_ifMoveCheck == 0 : return s1 = ginfo_cx : s2 = ginfo_cy repeat m_HeightCount ycnt =cnt * m_rect repeat m_WidthCount xcnt =cnt * m_rect if mP { boxf s1 + xcnt, s2 + ycnt, s1 + xcnt + m_rect, s2 + ycnt + m_rect } loop loop return //動体検知の中心点を取得 //mod_PixelData_MoveGetCenter モジュール変数, 中心点Xの位置が返される変数, 中心点Yの位置が返される変数 //戻り値 : 中心点に変化が見られた場合'1'を返す。それ以外は'0'を返す。 #modfunc mod_PixelData_MoveGetCenter var _px, var _py, local s1, local s2, local s3, local xcnt, local ycnt if m_ifPixelData == 0 : return 0 if m_ifMoveCheck == 0 : return 0 repeat m_HeightCount ycnt =cnt * m_rect repeat m_WidthCount xcnt =cnt * m_rect if mP { s1 += xcnt s2 += ycnt s3++ } loop loop if s3 != 0{ _px = s1 / s3 _py = s2 / s3 return 1 } return 0 //指定した色を透明色としクロマキー処理を行う //mod_PixelData_ChromakeyColor モジュール変数, 透明色R, 透明色G, 透明色B, 透明色とみなす閾値 #modfunc mod_PixelData_ChromakeyColor int _R, int _G, int _B, int _threshold, local threshold, local xcnt, local ycnt if m_ifPixelData == 0 : return 0 if m_ifChromakey == 0 : return 0 if m_ifChromakeyColor == 0 : m_ifChromakeyColor = 1 threshold = _threshold repeat m_HeightCount ycnt =cnt * m_rect repeat m_WidthCount xcnt =cnt * m_rect if m_ifSoftChromakey { sR = limit(abs(R - cR)*2, 0, 255) sG = limit(abs(G - cG)*2, 0, 255) sB = limit(abs(B - cB)*2, 0, 255) C = limit(int(double(abs(R - cR) + abs(G - cG) + abs(B - cB)) / 3), 0, 255) }else{ C = 255 } switch m_filter case 0 if _R-th<=R{ if _R+th>=R{ if _G-th<=G{ if _G+th>=G{ if _B-th<=B{ if _B+th>=B{ C = 0 } } } } } } swbreak case 1 if (_R-th>=m_pR(P))|(_R+th<=m_pR(P)) { if (_G-th>=m_pG(P))|(_G+th<=m_pG(P)) { if (_B-th>=m_pB(P))|(_B+th<=m_pB(P)) { C = 0 } } } swbreak swend loop loop return //クロマキー用ピクセルデータを取得する //mod_PixelData_ChromakeyBackGroundGet モジュール変数 #modfunc mod_PixelData_ChromakeyBackGroundGet local xcnt, local ycnt if m_ifPixelData == 0 : return 0 if m_ifChromakey == 0 : return 0 if m_ifChromakeyBackGround == 0 : m_ifChromakeyBackGround = 1 repeat m_HeightCount ycnt =cnt * m_rect repeat m_WidthCount xcnt =cnt * m_rect switch m_filter case 0 cR = R cG = G cB = B swbreak case 1 cR = m_pR(P) cG = m_pG(P) cB = m_pB(P) swbreak swend loop loop return //クロマキー用ピクセルデータを元にクロマキー処理を行う //mod_PixelData_ChromakeyBackGround モジュール変数, 透明化を行う閾値 #modfunc mod_PixelData_ChromakeyBackGround int _threshold, local threshold, local xcnt, local ycnt if m_ifPixelData == 0 : return 0 if m_ifChromakey == 0 : return 0 if m_ifChromakeyBackGround < 1 : return 0 : else : if m_ifChromakeyBackGround ! 2 : m_ifChromakeyBackGround = 2 threshold = _threshold repeat m_HeightCount ycnt =cnt * m_rect repeat m_WidthCount xcnt =cnt * m_rect //色の閾値を利用 switch m_filter case 0 if m_ifSoftChromakey { sR = limit(abs(R - cR)*2, 0, 255) sG = limit(abs(G - cG)*2, 0, 255) sB = limit(abs(B - cB)*2, 0, 255) C = limit(int(double(abs(R - cR) + abs(G - cG) + abs(B - cB)) / 3), 0, 255) }else{ C = 255 } if cR-th<=R{ if cR+th>=R{ if cG-th<=G{ if cG+th>=G{ if cB-th<=B{ if cB+th>=B{ C = 0 } } } } } } swbreak case 1 C = 255 if m_ifSoftChromakey { sR = limit(abs(m_pR(P) - cR), 0, 255) sG = limit(abs(m_pG(P) - cG), 0, 255) sB = limit(abs(m_pB(P) - cB), 0, 255) if (xcnt=2*m_rect)&(ycnt=2*m_rect):title ""+sG+" "+255 } if cR-th<=m_pR(P){ if cR+th>=m_pR(P){ if cG-th<=m_pG(P){ if cG+th>=m_pG(P){ if cB-th<=m_pB(P){ if cB+th>=m_pB(P){ C = 0 } } } } } } swbreak swend loop loop return //クロマキー処理を行った画像を描画する //mod_PixelData_ChromakeyDraw 背景色を描画するかどうかのフラグ, 背景色の色R, 背景色の色G, 背景色の色B #modfunc mod_PixelData_ChromakeyDraw int _ifBackGroundColor, int _R, int _G, int _B, local xcnt, local ycnt, local s1, local s2, local s3, local s4, local s5, local s6 if m_ifPixelData == 0 : return 0 if m_ifChromakey == 0 : return 0 if ((m_ifChromakeyColor == 0)|(m_ifChromakeyBackGround < 1)) == 0 : return 0 s1 = ginfo_cx : s2 = ginfo_cy repeat m_HeightCount ycnt = cnt * m_rect repeat m_WidthCount xcnt = cnt * m_rect switch C case 255 switch m_filter case 0 color R, G, B swbreak case 1 color m_pR(P), m_pG(P), m_pB(P) swbreak swend if m_rect <= 1{ pset s1 + xcnt, s2 + ycnt }else{ boxf s1 + xcnt, s2 + ycnt, s1 + xcnt + m_rect, s2 + ycnt + m_rect } swbreak case 0 if _ifBackGroundColor { color _R, _G, _B if m_rect <= 1{ pset s1 + xcnt, s2 + ycnt }else{ boxf s1 + xcnt, s2 + ycnt, s1 + xcnt + m_rect, s2 + ycnt + m_rect } } swbreak default //透明色のアルファチャンネル処理 switch m_filter case 0 s3 = double(abs(R - _R)) / 255 if R<=_R{ s4 = _R-s3*sR }else{ s4 = _R+s3*sR } s3 = double(abs(G - _G)) / 255 if G<=_G{ s5 = _G-s3*sG }else{ s5 = _G+s3*sG } s3 = double(abs(B - _B)) / 255 if B<=_B{ s6 = _B-s3*sB }else{ s6 = _B+s3*sB } color s4, s5, s6 if m_rect <= 1{ pset s1 + xcnt, s2 + ycnt }else{ boxf s1 + xcnt, s2 + ycnt, s1 + xcnt + m_rect, s2 + ycnt + m_rect } swbreak case 1 s3 = abs(m_pR(P) - _R) s4 = double(s3) / 255 if m_pR(P)<=_R{ s5 = _R-s4*sR }else{ s5 = _R+s4*sR } s3 = abs(m_pG(P) - _G) s4 = double(s3) / 255 if m_pG(P)<=_R{ s6 = _G-s4*sG }else{ s6 = _G+s4*sG } s3 = abs(m_pB(P) - _B) s4 = double(s3) / 255 if m_pB(P)<=_R{ s7 = _B-s4*sB }else{ s7 = _B+s4*sB } color s5, s6, s7 if m_rect <= 1{ pset s1 + xcnt, s2 + ycnt }else{ boxf s1 + xcnt, s2 + ycnt, s1 + xcnt + m_rect, s2 + ycnt + m_rect } swbreak swend if m_rect <= 1{ pset s1 + xcnt, s2 + ycnt }else{ boxf s1 + xcnt, s2 + ycnt, s1 + xcnt + m_rect, s2 + ycnt + m_rect } swbreak swend loop loop return //クロマキーで描画される物体の中心点を取得 //mod_PixelData_MoveGetCenter モジュール変数, 中心点Xの位置が返される変数, 中心点Yの位置が返される変数 //戻り値 : 中心点に変化が見られた場合'1'を返す。それ以外は'0'を返す。 #modfunc mod_PixelData_ChromakeyCenter var _px, var _py, local s1, local s2, local s3 if m_ifPixelData == 0 : return 0 if m_ifChromakey == 0 : return 0 if ((m_ifChromakeyColor == 0)|(m_ifChromakeyBackGround < 1)) == 0 : return 0 repeat m_HeightCount ycnt =cnt * m_rect repeat m_WidthCount xcnt =cnt * m_rect if C == 0 { s1 += xcnt s2 += ycnt s3++ } loop loop if s3 != 0{ _px = s1 / s3 _py = s2 / s3 return 1 } return 0 #global // サンプルの選択 ///////////////////////////////////////////////////// #define SAMPLE 3 //0 : 画像を減色するプログラム //1 : カメラを使った動体検知プログラム //2 : カメラを使ったクロマキー(背景色透明化)プログラム //3 : カメラを使った登録した背景を透明化するプログラム //4 : カメラを使った登録した背景を透明化(ソフトクロマキー)するプログラム /////////////////////////////////////////////////////////////////////// *@// 画像を減色するプログラム ////////////////////////// #if SAMPLE == 0 ti=timer() buffer 1 : picload dir_exe + "/docs/cg.gif" mx = ginfo_winx my = ginfo_winy screen 0, 800, 300 sysfont 17 mes "フィルタリング前" gcopy 1, 0, 0, mx, my newmod pd, PixelData, 1, 0, 0, mx, my //フィルタリングを行う画像がある位置を設定しオブジェクトを作成 mod_PixelData_Get pd //ピクセルデータを取得 mod_PixelData_Filter pd, 1, 30, 0 //減色フィルタをかける gsel 0 color pos 400, 0 redraw 0 mes "フィルタリング後" mes ""+(timer()-ti)+"秒経過" mod_PixelData_Draw pd //フィルタリング後の画像を描画する redraw 1 stop #endif *@// カメラを使った動体検知プログラム ////////////////////////////////////////////////////// #if SAMPLE == 1 screen 0 title "0" sysfont 17 onexit *owari buffer 1 title "1" cvcapture 0, 0 buffer 2 title "2" newmod pd, PixelData, 2, 0, 0, 320, 240, 1 gmode 1 *main gsel 1 cvgetcapture cvgetimg gsel 2 pos 0,239 : gzoom 320,-240,1,0,0,320,240 mod_PixelData_Get pd, 4 //mod_PixelData_Filter pd, 1, 30, 0 gsel 0 redraw 0 #if 1 pos 0, 0 mod_PixelData_Draw pd #else color 255,255,255 boxf 0,0,320,240 #endif mod_PixelData_MoveCheck pd, a, 100, 1 pos 0,0 color 255 mod_PixelData_MoveDraw pd mod_PixelData_MoveGetCenter pd, x, y if stat : ifcenter = 1 if ifcenter { color 0, 0, 255 boxf x, y, x+4, y+4 color pos x+5, y+5 : mes "中心点" } title ""+a if a>20{ color pos 322, 1 + 16 * count : count++ mes "何かが動いています" if count == 30 : color 255,255,255 : boxf 322,1 : count = 0 } redraw 1 wait 1 goto *main *owari cvendcapture end #endif *@// カメラを使った指定した色の透明化を行うプログラム ////////////////////////////////////////////////////// #if SAMPLE == 2 screen 0 title "0" sysfont 17 onexit *owari buffer 1 title "1" cvcapture 0, 0 buffer 2 title "2" newmod pd, PixelData, 2, 0, 0, 320, 240, 0, 1 gmode 1 *main gsel 1 cvgetcapture cvgetimg gsel 2 pos 0,239 : gzoom 320,-240,1,0,0,320,240 mod_PixelData_Get pd, 4 //mod_PixelData_Filter pd, 1, 30, 0 gsel 0 redraw 0 mod_PixelData_ChromakeyColor pd, 188, 129, 125, 80 pos 0,0 mod_PixelData_ChromakeyDraw pd, 1, 255, 0, 255 redraw 1 wait 1 goto *main *owari cvendcapture end #endif *@// カメラを使った登録した背景を透明化するプログラム ////////////////////////////////////////////////////// #if SAMPLE == 3 screen 0 title "0" sysfont 17 onexit *owari buffer 1 title "1" cvcapture 0, 0 buffer 2 title "2" newmod pd, PixelData, 2, 0, 0, 320, 240, 0, 1 gmode 1 gsel 1 cvgetcapture cvgetimg gsel 2 pos 0,239 : gzoom 320,-240,1,0,0,320,240 wait 10 mod_PixelData_Get pd, 1 mod_PixelData_ChromakeyBackGroundGet pd *main gsel 1 cvgetcapture cvgetimg gsel 2 pos 0,239 : gzoom 320,-240,1,0,0,320,240 mod_PixelData_Get pd, 1 //mod_PixelData_Filter pd, 1, 30, 0 gsel 0 redraw 0 color 255, 255, 255 boxf 0, 0, 320, 240 color line 0, 0, 320, 240 : line 320, 0, 0, 240 mod_PixelData_ChromakeyBackGround pd, 70 pos 0,0 mod_PixelData_ChromakeyDraw pd, 0, 255, 255, 255 mod_PixelData_ChromakeyCenter pd, x, y if stat : ifcenter = 1 if ifcenter { color 0 , 0, 255 boxf x, y, x+2, y+2 color pos x, y : mes "中心点" } color 255 redraw 1 wait 1 goto *main *owari cvendcapture end #endif *@// カメラを使った登録した背景を透明化(ソフトクロマキー)するプログラム ////////////////////////////////////////////////////// #if SAMPLE == 4 screen 0 title "0" sysfont 17 onexit *owari buffer 1 title "1" cvcapture 0, 0 buffer 2 title "2" newmod pd, PixelData, 2, 0, 0, 320, 240, 0, 1, 1 gmode 1 gsel 1 cvgetcapture cvgetimg gsel 2 pos 0,239 : gzoom 320,-240,1,0,0,320,240 wait 10 mod_PixelData_Get pd, 4 mod_PixelData_ChromakeyBackGroundGet pd *main gsel 1 cvgetcapture cvgetimg gsel 2 pos 0,239 : gzoom 320,-240,1,0,0,320,240 mod_PixelData_Get pd, 4 //mod_PixelData_Filter pd, 1, 30, 0 gsel 0 redraw 0 color 255,255,255 boxf 0,0,320,240 color line 0, 0, 320, 240 : line 320, 0, 0, 240 mod_PixelData_ChromakeyBackGround pd, 120 pos 0,0 mod_PixelData_ChromakeyDraw pd, 0, 255, 255, 255 mod_PixelData_ChromakeyCenter pd, x, y if stat : ifcenter = 1 if ifcenter { color 0 , 0, 255 boxf x, y, x+4, y+4 color pos x, y : mes "中心点" } color 255 redraw 1 wait 1 goto *main *owari cvendcapture end #endif