「外接矩形座標」を求める
外接矩形座標を求めます。(矩形=長方形)
画像処理のイメージ図
このサンプルプログラムで実行される画像処理フローを解説します。
①カメラからカラー画像が入力されます(「入力画像」)。
②入力されたカラー画像を2値化処理し、ブロッブを選定します(「2値化処理画像」)。
③指定された番号のブロッブに対して、ブロッブの外接矩形座標を求めます。
④ブロッブの外接矩形座標は、解析実行画面に表示されます。
また、出力する座標XY1とXY2は下図の座標です。
サンプルプログラムの実行
サンプルプログラムを実行すると、画面上にブロッブの外接矩形と座標をリアルタイムに表示します。
ライブラリ関数
Vextent int Vextent (int *x_min, int *x_max, int *y_min, int *y_max) 戻り値 正常終了の時は、0を返します。それ以外は、以下の値を返します。 6:画像解析していない 7:白がない 10:ブロッブ選択していない 引数 *x_min 最小X座標(ピクセル) *x_max 最大X座標(ピクセル) *y_min 最小Y座標(ピクセル) *y_max 最大Y座標(ピクセル) 説明 指定ブロッブの外接矩形を求める。
ソースコード
/////////////////////////////////////////////////////////
// extent.cpp : 「外接矩形座標」を求めるサンプルプログラム
//
// このプログラムは画像ファイルを入力し、
// 指定したブロブの「外接矩形座標」を求めるサンプルプログラムです。
//
// パラメータはファイルから入力します。
// ファイル名:extent.txt
//
// 1行目:ブロブ番号
/////////////////////////////////////////////////////////
#include "stdafx.h"
#include "extent.h"
#include <math.h>
#include <conio.h>
#include "MvcDib.h"
#include "MvcBin.h"
#include "MvcUtil.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////////////////////////////////////
// 関数宣言
///////////////////////////////////////////////////////
static int iInit(void); // 初期化処理
static int iWinReg(); // ウィンドウの登録
static int iCreWin(); // ウィンドウの作成
static void iMsgLoop(void); // メッセージループ
// ウィンドウプロシージャ
static LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam);
///////////////////////////////////////////////////////
// グローバル変数
///////////////////////////////////////////////////////
char img_name[256] = "Image/Blob/Blob16.bmp"; // 画像ファイル名
HANDLE srcDib, dstDib; // 入力画像、処理画像のハンドル
int iWidth, iHeight; // 画像の横幅、縦幅
RECT rc; // 表示範囲
_TCHAR appIni[256]; // パラメータファイルのフルパス
int blob_no = 1; // ブロブ番号
int x_min, x_max, y_min, y_max; // 格納バッファ
char text1[256]; // 結果表示用テキストバッファ
char text2[256];
char text3[256];
DWORD dwTime;
// MFC用グローバル変数
CWinApp theApp;
HINSTANCE hInst;
WNDCLASSEX wc;
using namespace std;
HWND g_hWnd0 = NULL; // 入力画像表示ウィンドウハンドル
HWND g_hWnd1 = NULL; // 処理画像用ウインドウハンドル
///////////////////////////////////////////////////////
// main関数
///////////////////////////////////////////////////////
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int i;
FILE *fp; // 入力ファイル
char s[256]; // 入力パラメータ用バッファ
int sort = 0; // ソート方法
double xsize = 1.0; // X方向のピクセルサイズ
double ysize = 1.0; // Y方向のピクセルサイズ
int iThresh; // 2値化のしきい値
DWORD lut[256]; // LUT
/*---- 前処理 -----------------------------------*/
// 初期化処理
iInit();
if(MvcBin_Init() != 0)
{
AfxMessageBox("MvcBin 初期化処理エラー\n");
exit(1);
}
if(MvcUtil_Init() != 0)
{
AfxMessageBox("MvcUtil 初期化処理エラー\n");
exit(1);
}
// ファイルオープン
if ((fp = fopen(appIni, "r")) == NULL) {
printf("file open error!!\n");
exit(1);
}
// 入力パラメータの読み込み
fgets(s, 256, fp);
// ファイルクローズ
fclose(fp);
blob_no = atoi(s);
printf("ブロブの「外接矩形座標」を求めるサンプルプログラム\n\n");
// 設定パラメータの表示
printf("【設定パラメータ】\n");
printf("\tブロブ番号 : %d\n", blob_no);
// キー入力待ち
printf("\nキーを入力すると処理を開始します。\n\n");
printf("もう一度キーを入力すると終了します。\n");
int ch;
ch = getch();
// 画像の読み込み
srcDib = MvcDib_Open(img_name);
// 画像サイズを求める
iWidth = MvcDib_GetXsize(srcDib); // 横幅
iHeight = MvcDib_GetYsize(srcDib); // 縦幅
// 表示範囲を設定(画面全体)
rc.top = 0;
rc.left = 0;
rc.right = iWidth - 1;
rc.bottom = iHeight - 1;
/*---- ブロブ解析 -------------------------------*/
dstDib = MvcDib_Create(iWidth, iHeight, 1, 4);
// カラー画像を濃淡画像に変換
MvcDib_GrayFromColor(dstDib, srcDib, 0);
// 処理対象画像をセット
MvcBin_SetHDIB(dstDib);
// 解析範囲の指定(ここでは画像全体を指定)
Vset_window(0, 0, 0, iWidth-1, iHeight-1);
// ピクセルサイズを設定
Vset_pixel_size(xsize, ysize);
// しきい値の算出(判別識別法)
iThresh = Vget_thresh_level(0, 0, 255, 1, 0);
// LUTの作成
for(i=0; i<iThresh; i++)
lut[i] = 0;
for(i=iThresh; i<256; i++)
lut[i] = 0xff;
// LUTを設定
Vset_lut(lut);
// 処理時間計測開始
Vstart_timer();
// ブロブ解析の実行
Vanal_s(0, sort, 0, 0);
// 指定されたブロブを選択
Vsel_blob_s(blob_no);
// 指定されたブロブの「外接矩形座標」を求める
Vextent(&x_min, &x_max, &y_min, &y_max); // 外接矩形
// 処理時間計測終了
Vread_Utimer(&dwTime);
/*---- 処理結果の表示 ----------------------------*/
printf("\n【処理結果】\n");
printf("\t処理時間 : %.2lf msec\n",(double)dwTime / 1000);
printf("\t外接矩形座標 : (%d,%d)\n", x_min, y_min);
printf("\t : (%d,%d)\n", x_max, y_max);
// 描画用のテキストを設定
sprintf(text1, "処理時間 : %.2lf msec",(double)dwTime / 1000);
sprintf(text2, "外接矩形座標 : (%d,%d)", x_min, y_min);
sprintf(text3, " : (%d,%d)", x_max, y_max);
// 描画用のlutを設定
MvcDib_SetLut(dstDib, lut);
// ウィンドウの登録
iWinReg();
// 処理結果を表示
iCreWin();
// メッセージループ
iMsgLoop();
/*---- 終了処理 ----------------------------------*/
// 画像メモリの開放
MvcDib_Destroy(srcDib);
MvcDib_Destroy(dstDib);
// 終了処理
MvcUtil_Fini();
MvcBin_Fini();
return 0;
}
///////////////////////////////////////////////////////
// ウィンドウプロシージャ
//
// ここに描画などのイベント処理を記述します
//
///////////////////////////////////////////////////////
static LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
HDC hDC;
PAINTSTRUCT ps;
switch(message)
{
// 描画処理
case WM_PAINT:
// 入力画像の描画
if(g_hWnd0 != NULL)
{
hwnd = g_hWnd0;
hDC = BeginPaint(hwnd, &ps);
MvcDib_Paint2(hDC,srcDib,&rc,&rc);
EndPaint(hwnd, &ps);
}
// 処理画像の描画
if(g_hWnd1 != NULL)
{
hwnd = g_hWnd1;
hDC = BeginPaint(hwnd, &ps);
MvcDib_Paint2(hDC,dstDib,&rc,&rc); // 2値画像を描画
MvcUtil_DrawLine( x_min, y_min, x_min, y_max, RED); // 外接矩形の描画
MvcUtil_DrawLine( x_max, y_min, x_max, y_max, RED);
MvcUtil_DrawLine( x_min, y_min, x_max, y_min, RED);
MvcUtil_DrawLine( x_min, y_max, x_max, y_max, RED);
MvcUtil_DrawText( 0, 0, text1, CYAN); // テキストを描画
MvcUtil_DrawText( 0, 20, text2, CYAN);
MvcUtil_DrawText( 0, 40, text3, CYAN);
Vdisp_blob_number(hDC,0, RED); // ブロブ番号を表示する
Vsel_blob_s(blob_no);
Vout_border(hDC, 0, 0, GREEN); // 輪郭を描画
MvcUtil_Paint(hDC); // ウィンドウに表示
EndPaint(hwnd, &ps);
}
break;
// キー処理
case WM_KEYDOWN:
PostQuitMessage(0);
break;
// 閉窓処理
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wparam,lparam);
}
return 0;
}
///////////////////////////////////////////////////////
// 初期化処理
///////////////////////////////////////////////////////
static int iInit(void)
{
// MFCの初期化
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
printf("MFC initialization failed");
return 1;
}
// インスタンスハンドルを取得
hInst = AfxGetInstanceHandle();
// 実行ディレクトリの取得とパラメータファイル名の設定
_TCHAR path[256], appDir[256];
_TCHAR drive[256], dir[256];
_TCHAR exen[256], params[256];
GetModuleFileName( NULL, path, sizeof(path) );
_tsplitpath( path, drive, dir, exen, NULL );
if (dir[_tcslen(dir) - 1] == '\\')
dir[_tcslen(dir) - 1] = '\0';
_tcscpy( appDir, drive );
_tcscat( appDir, dir );
_tcscpy( appIni, appDir );
_tcscat( appIni, _T("\\") );
sprintf(params,"%s.txt", exen);
_tcscat( appIni, params );
return 0;
}
///////////////////////////////////////////////////////
// ウィンドウクラスの登録
///////////////////////////////////////////////////////
static int iWinReg(void)
{
// ウィンドウクラスの情報を設定
wc.cbSize = sizeof(wc); // 構造体サイズ
wc.style = CS_HREDRAW | CS_VREDRAW; // スタイル
wc.lpfnWndProc = WndProc; // ウィンドウプロシージャ
wc.cbClsExtra = 0; // 拡張情報1
wc.cbWndExtra = 0; // 拡張情報2
wc.hInstance = hInst; // インスタンスハンドル
wc.hIcon = (HICON)LoadImage( // アイコン
NULL,
MAKEINTRESOURCE(IDI_APPLICATION),
IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED);
wc.hIconSm = wc.hIcon; // 子アイコン
wc.hCursor = (HCURSOR)LoadImage( // マウスカーソル
NULL, MAKEINTRESOURCE(IDC_ARROW),
IMAGE_CURSOR,
0, 0, LR_DEFAULTSIZE | LR_SHARED);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // ウィンドウ背景
wc.lpszMenuName = NULL; // メニュー名
wc.lpszClassName = "Mvc Sample Program"; // ウィンドウクラス名
// ウィンドウクラスを登録
if( RegisterClassEx( &wc ) == 0 )
return 1;
return 0;
}
///////////////////////////////////////////////////////
// ウィンドウの表示
///////////////////////////////////////////////////////
static int iCreWin( void)
{
// 入力画像ウィンドウの作成
g_hWnd0 = CreateWindow(
wc.lpszClassName, // ウィンドウクラス名
"入力画像", // タイトルバーに表示する文字列
WS_OVERLAPPEDWINDOW, // ウィンドウの種類
100, // ウィンドウを表示する位置(X座標)
100, // ウィンドウを表示する位置(Y座標)
iWidth + 8, // ウィンドウの幅
iHeight + 34, // ウィンドウの高さ
NULL, // 親ウィンドウのウィンドウハンドル
NULL, // メニューハンドル
hInst, // インスタンスハンドル
NULL // その他の作成データ
);
// ウインドウの表示
ShowWindow(g_hWnd0, SW_SHOW);
// 処理画像ウィンドウの作成
g_hWnd1 = CreateWindow(
wc.lpszClassName, // ウィンドウクラス名
"処理画像", // タイトルバーに表示する文字列
WS_OVERLAPPEDWINDOW, // ウィンドウの種類
400, // ウィンドウを表示する位置(X座標)
100, // ウィンドウを表示する位置(Y座標)
iWidth + 8, // ウィンドウの幅
iHeight + 34, // ウィンドウの高さ
NULL, // 親ウィンドウのウィンドウハンドル
NULL, // メニューハンドル
hInst, // インスタンスハンドル
NULL // その他の作成データ
);
// ウインドウの表示
ShowWindow(g_hWnd1, SW_SHOW);
//ウィンドウをアクティブにする
SetForegroundWindow (g_hWnd0);
SetForegroundWindow (g_hWnd1);
return 0;
}
///////////////////////////////////////////////////////
// メッセージループ
///////////////////////////////////////////////////////
static void iMsgLoop(void)
{
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}