//★ Win32 API Mark Rect 前田 稔
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
struct BITMAPINFOHEADER
{
・・・ Image Guid を参照 ・・・
};
public class MyForm : Form
{ Face App;
int val= 3000;
public MyForm()
{
App = new Face();
App.OpenFile();
Width = App.m_bmp.Width;
Height = App.m_bmp.Height+32;
App.InitDib();
App.CopyBmp(App.m_DibDC);
App.CopyBmp(App.m_MaskDC);
Paint += new PaintEventHandler(MyHandler);
MouseDown += new MouseEventHandler(OnMyMouseDown);
}
private void MyHandler(object sender, PaintEventArgs e)
{
Graphics g;
g = e.Graphics;
if (App.m_bmp == null) Application.Exit();
App.ViewMask(g,0,0);
App.DrawRect(g);
}
private void OnMyMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) //マウスの左ボタン
{ val+= 1000;
VerMsg("val: ", val);
App.Edge(val);
}
if (e.Button == MouseButtons.Right) //マウスの右ボタン
{ val = 5000;
App.CopyBmp(App.m_MaskDC);
}
Invalidate();
}
public void VerMsg(string msg, int v)
{
string wstr;
wstr = msg + v.ToString();
this.Text = wstr;
}
}
//☆ Face Object Class
unsafe class Face
{
public Bitmap m_bmp; // 入力画像
public Bitmap m_mark; // 入力マーク画像
public IntPtr m_Dib; // DIB 画像
public IntPtr m_DibDC; // DIB DC
public byte *dat; // DIB ピクセルデータ
public IntPtr m_Mask; // Mask 画像
public IntPtr m_MaskDC; // Mask DC
public byte *msk; // Mak ピクセルデータ
string ImgFile = "";
public const int BI_RGB = 0;
public const int DIB_RGB_COLORS = 0;
public const int SRCCOPY = 0xcc0020;
int[,] vect = new int[9,2] //エッジ検出テーブル
{ {-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,0}, {0,1}, {1,-1}, {1,0}, {1,1} };
int[] hCoef = new int[9]{ 1, 0, -1, 2, 0, -2, 1, 0, -1 };
int[] vCoef = new int[9]{ 1, 2, 1, 0, 0, 0, -1, -2, -1 };
public Point[] m_pt = new Point[7]; //Land Mark Table
Point pt; //Mark Point
int[,] mkt = new int[5,5] //Mark 検索パラメータ(BMP 座標)
{ { 123,46,133,95,0 },
{ 72,72,96,124,2 },{ 156,72,184,120,3 },
{ 70,172,112,202,3 },{ 144,172,186,202,2 } };
[DllImport("gdi32.dll")]
・・・ Image Guid を参照 ・・・
// Constructor
public Face()
{
Reset();
}
// 入力画像を描画
public void OpenFile()
{
OpenFileDialog opendlg = new OpenFileDialog();
opendlg.Filter = "画像ファイル (*.bmp)|*.bmp|すべてのファイル (*.*)|*.*";
if (opendlg.ShowDialog() == DialogResult.OK)
{ ImgFile = opendlg.FileName; }
try
{ Reset();
m_bmp = new Bitmap(ImgFile);
m_mark = new Bitmap("C:\\DATA\\Test\\mark.gif");
}
catch
{ MessageBox.Show("画像ファイルが読めません!", ImgFile);
return;
}
}
// Destructor
~Face()
{ Reset(); }
// 入力画像を描画
public void Reset()
{ if (m_DibDC!=null) DeleteDC(m_DibDC);
if (m_Dib!=null) DeleteObject(m_Dib);
if (m_MaskDC!=null) DeleteDC(m_MaskDC);
if (m_Mask!=null) DeleteObject(m_Mask);
if (m_bmp!=null) m_bmp.Dispose();
m_pt[0].X = 0;
}
// 入力画像を描画
public void View(Graphics g, int x, int y)
{ if (m_bmp != null) g.DrawImage(m_bmp, x, y); }
// 一個のマーク画像を描画
public void DrawMark(Graphics g, int x, int y)
{ if (m_mark != null) g.DrawImage(m_mark, x, y); }
// マーク画像(m_pt[7])を描画
public void DrawMark(Graphics g)
{ if (m_mark == null || m_pt[0].X == 0) return;
for(int i=0; i<7; i++) g.DrawImage(m_mark, m_pt[i].X, m_bmp.Height-m_pt[i].Y);
}
// m_DibDC(DIB) の画像を描画する
public void ViewDib(Graphics g, int x, int y)
{
if (m_DibDC == null) return;
IntPtr hDC = g.GetHdc();
BitBlt(hDC, x, y, m_bmp.Width, m_bmp.Height, m_DibDC, 0, 0, SRCCOPY);
g.ReleaseHdc(hDC);
}
// マスク画像を描画する
public void ViewMask(Graphics g, int x, int y)
{
if (m_MaskDC == null) return;
IntPtr hDC = g.GetHdc();
BitBlt(hDC, x, y, m_bmp.Width, m_bmp.Height, m_MaskDC, 0, 0, SRCCOPY);
g.ReleaseHdc(hDC);
}
// hDC ← Bitmap m_bmp イメージデータの転送
public void CopyBmp(IntPtr hDC)
{
IntPtr hBmpSrc = m_bmp.GetHbitmap();
Graphics gdraw = Graphics.FromImage(m_bmp);
IntPtr srcHDC = gdraw.GetHdc();
SelectObject(srcHDC, hBmpSrc);
BitBlt(hDC, 0, 0, m_bmp.Width, m_bmp.Height, srcHDC, 0, 0, SRCCOPY);
DeleteObject(hBmpSrc);
gdraw.ReleaseHdc(srcHDC);
}
// 検索矩形を表示する(BMP座標⇒ディスプレイ座標)
public void DrawRect(Graphics g)
{ int[] t = new int[5];
for(int i=0; i<5; i++)
{ t[0]= mkt[i,0];
t[1]= (m_bmp.Height-1) - mkt[i,1];
t[2]= mkt[i,2];
t[3]= (m_bmp.Height-1) - mkt[i,3];
t[4]= mkt[i,4];
Rect(g, t);
}
}
// ディスプレイ座標で矩形を描画
public void Rect(Graphics g, int[] t)
{
Pen p = new Pen(Color.Black, 1);
g.DrawLine(p, t[0], t[1], t[2], t[1]);
g.DrawLine(p, t[0], t[3], t[2], t[3]);
g.DrawLine(p, t[0], t[1], t[0], t[3]);
g.DrawLine(p, t[2], t[1], t[2], t[3]);
p.Dispose();
}
//☆ Dib, Mask の初期化
unsafe public void InitDib()
{
・・・ Image Guid を参照 ・・・
fixed (void* ppvBits = &dat)
{ m_Dib = CreateDIBSection(hdc, bi, 0, (IntPtr)ppvBits, (IntPtr)null, 0);
if (m_Dib == null) MessageBox.Show("CreateDIBSection error");
}
m_DibDC = CreateCompatibleDC(hdc);
SelectObject(m_DibDC, m_Dib);
fixed (void* ppvBits2 = &msk)
{ m_Mask = CreateDIBSection(hdc, bi, 0, (IntPtr)ppvBits2, (IntPtr)null, 0);
if (m_Mask == null) MessageBox.Show("CreateDIBSection error");
}
m_MaskDC = CreateCompatibleDC(hdc);
SelectObject(m_MaskDC, m_Mask);
ReleaseDC(IntPtr.Zero, hdc);
}
// *dat を参照して *msk にエッジ画像を作成
public void Edge(int val)
{
if (m_DibDC == null) return;
for(int y=1; y<m_bmp.Height-1; y++)
for(int x=1; x<m_bmp.Width-1; x++)
{
if (Sobel(x, y, val)) MASK(x,y,0,0,0);
else MASK(x,y,255,255,255);
}
}
// 座標[x,y]周辺のピクセル(*dat)を調べてエッジを検出する
public bool Sobel(int x, int y, int val)
{ int[] fx = new int[3]; //横3色分
int[] fy = new int[3]; //縦3色分
int dx, dy;
byte *pt;
fx[0]= fx[1]= fx[2]= 0;
fy[0]= fy[1]= fy[2]= 0;
for(int i=0; i<9; i++)
{
dx = x + vect[i,0];
dy = y + vect[i,1];
pt = dat+(dy*m_bmp.Width+dx)*4;
for(int c=0; c<3; c++)
{ fx[c] += *(pt+c) * hCoef[i];
fy[c] += *(pt+c) * vCoef[i];
}
}
for(int c=0; c<3; c++)
if (fx[c]*fx[c]+fy[c]*fy[c] > val) return true;
return false;
}
// *msk(y, x, c) の色を取得
public byte MASK(int x, int y, int c)
{
byte *pt;
pt = msk+(y*m_bmp.Width+x)*4+c;
return *pt;
}
// *msk(y, x) に R,G,B を設定(A はそのまま)
public void MASK(int x, int y, byte r, byte g, byte b)
{
byte *pt;
pt = msk+(y*m_bmp.Width+x)*4;
*pt = b;
*(pt+1)= g;
*(pt+2)= r;
}
// Mark 検索パラメータを使って pt_t[7] にマーク座標を格納する
public void LandMark()
{
int[] t = new int[5];
m_pt[0].X = 128;
m_pt[0].Y = 128;
m_pt[1].X = 128;
m_pt[1].Y = 192;
for(int n=0; n<5; n++)
{ for(int i=0; i<5; i++) t[i] = mkt[n, i];
LandMK(t);
m_pt[n+2]= pt;
}
}
// m_Mask の画像から t[5] の範囲で Land Mark を検出する
// t[0],t[1]=左下座標(X,Y), t[2],t[3]=右上座標(X,Y), t[4]=検索方向
public void LandMK(int[] t)
{ int w,h,cx,cy,x,y,x1,x2,y1,y2;
pt.X = pt.Y = 0;
w= t[2]-t[0];
h= t[3]-t[1];
cx= t[0]+w/2;
cy= t[1]+h/2;
switch(t[4])
{ case 0: //上方向
for(y=0; y<h; y++)
for(x=0; x<w/2; x++)
{
y1= t[1]+y;
x1= cx+x;
x2= cx-x;
if (MASK(x1,y1,0)==0)
{ pt.X= x1;
pt.Y= y1;
return;
}
if (MASK(x2,y1,0)==0)
{ pt.X= x2;
pt.Y= y1;
return;
}
}
break;
case 1: //下方向
for(y=0; y<h; y++)
for(x=0; x<w/2; x++)
{
y1= t[3]-y;
x1= cx+x;
x2= cx-x;
if (MASK(x1,y1,0)==0)
{ pt.X= x1;
pt.Y= y1;
return;
}
if (MASK(x2,y1,0)==0)
{ pt.X= x2;
pt.Y= y1;
return;
}
}
break;
case 2: //右方向
for(x=0; x<w; x++)
for(y=0; y<h/2; y++)
{
x1= t[0]+x;
y1= cy+y;
y2= cy-y;
if (MASK(x1,y1,0)==0)
{ pt.X= x1;
pt.Y= y1;
return;
}
if (MASK(x1,y2,0)==0)
{ pt.X= x1;
pt.Y= y2;
return;
}
}
break;
case 3: //左方向
for(x=0; x<w; x++)
for(y=0; y<h/2; y++)
{
x1= t[2]-x;
y1= cy+y;
y2= cy-y;
if (MASK(x1,y1,0)==0)
{ pt.X= x1;
pt.Y= y1;
return;
}
if (MASK(x1,y2,0)==0)
{ pt.X= x1;
pt.Y= y2;
return;
}
}
break;
}
}
}
class image01
{
[STAThread]
public static void Main()
{
MyForm mf = new MyForm();
Application.Run(mf);
}
}
|