Extent
  

「外接矩形座標」を求める

外接矩形座標を求めます。(矩形=長方形)

画像処理のイメージ図

このサンプルプログラムで実行される画像処理フローを解説します。
①カメラからカラー画像が入力されます(「入力画像」)。
②入力されたカラー画像を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);
	}
}