こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ビットマップを二値化した後の座標取得のご相談

ビットマップを二値化した後の座標取得のご相談

最近VB6.0からVC++2008(Express Edition)に乗り換えて画像処理を試みています(WinXP).現在,長方形が写っているビットマップ画像を二値化して,指定範囲内の長方形の平均高さ(白を抽出)を調べようとしています.WEBや文献など調べて,二値化するところまではできたのですが,二値化後の白黒画像の座標値の読み方が分からないため,長方形の高さを算出することができません.もしよろしければご助言いただけましたら幸いに思います.

───────────────────────────────────
VB6.0プログラム(二値化後の処理の部分)
Dim Xmin As Double, Xmax As Double //X方向
Dim Ymin As Double, Ymax As Double //Y方向
Dim SumY As Double, AveY As Double
Dim Pix As Double
'
Xmin = 0
Xmax = Shape1.Width
SumY = 0  //長方形の高さの合計
AveY = 0  //長方形の高さの平均
'
For X = Shape1.Left To Shape1.Left + Shape1.Width
Ymin = 0
Ymax = 0
'
For Y = Shape1.Top To Shape1.Top + Shape1.Height //囲んだ四角部分において
'
  //※この下の部分をVC++2008でどのようにすれはいいかわかりません・・・
If picturebox1.Point(X, Y) = RGB(255, 255, 255) Then //白があれば
If Ymin = 0 Then //Yminが0であれば
Ymin = Y //YminはY
End If
If Ymax < Y Then //YmaxがYより小さかったら
Ymax = Y //YmaxはY
End If
End If
'
Next Y
SumY = SumY + Ymax - Ymin //Xごとの長方形の高さの合計
Next X
'
AveY = SumY / Xmax //平均高さの算出

───────────────────────────────────
ここからVC++2008(二値化と計算を一気に行えればいいなと思ってます)
for (j = 0; j < rect.Height; j++)
{
 for (i = 0; i < rect.Width; i++){
//輝度値の取得
B = pBuf[i * Step + j * bmpData->Stride];//青
G = pBuf[i * Step + 1 + j * bmpData->Stride];//緑
R = pBuf[i * Step + 2 + j * bmpData->Stride];//赤

//輝度値の設定(二値化)
if ((B >= Threshold) || (G >= Threshold) || (R >= Threshold))
{
//白に変換
 pBuf[i * Step + j * bmpData->Stride] = 255;//青
 pBuf[i * Step + 1 + j * bmpData->Stride] = 255;//緑
 pBuf[i * Step + 2 + j * bmpData->Stride] = 255;//赤

 //※ここに何かいれればいいと思うのですが,上記の
 //※If(picturebox1.Point(X,Y)=RGB(255,255,255))に代わる書き方が分かりません…
}
else
{
//黒に変換
pBuf[i * Step + j * bmpData->Stride] = 0;//青
pBuf[i * Step + 1 + j * bmpData->Stride] = 0;//緑
pBuf[i * Step + 2 + j * bmpData->Stride] = 0;//赤
}
}
参照WEB http://imagingsolution.blog107.fc2.com/blog-entry-40.htm

投稿日時 - 2010-06-03 17:20:37

QNo.5942244

すぐに回答ほしいです

質問者が選んだベストアンサー

参照WEB元の者です。
私もVB6.0からC++/CLIに乗り換えたクチですが、VB6.0のPSet、Pointは.NETでは,
SetPixel、GetPixelとなります。
そのため今回の場合は
if (bmp->GetPixel(i, j) == Color::White)
という感じになると思います。(やった事が無いので未確認ですが...)

ただ、二値化した後の画像データ(Bitmap)をFormat8bppIndexedを使ってモノクロの8Bitのビットマップにし、pBuf[i + j * bmpData->Stride] のように輝度値を参照した方がオススメです。

当然ですが、この場合は
if (pBuf[i + j * bmpData->Stride] == 255)
となります。

投稿日時 - 2010-06-03 23:56:38

補足

ご助言いただきました内容を参考に下記の様に変更をしてみました.その結果,指定範囲内の最大値ymaxを取得することはできたのですが・・・最小値yminがどうしても0のままになってしまいます.どこかおかしな部分がありましたら,ご指摘いただけましたら幸いに思います,よろしくお願い致します.(ご助言いただきました内容と変更した内容が全く異なっていましたら申し訳ございません・・・)

int i, j;//i:x方向,j:y方向
double ymin,ymax,y;
int Bright;//モノクロ輝度値
int B, G, R;//カラー輝度値
int BitCount;
int Step;
Byte Threshold;

//しきい値の取得
bool result = Byte::TryParse(textBox1->Text, Threshold);
if (result == false) return;

//測定範囲の取得(略)

//輝度値を取得、設定領域(四角枠)作成
Rectangle rect = System::Drawing::Rectangle(X0, Y0, W, H);

//Lock
Imaging::BitmapData^ bmpData =
bmp->LockBits(rect, Imaging::ImageLockMode::ReadWrite, bmp->PixelFormat);

Byte* pBuf = (Byte*)bmpData->Scan0.ToPointer(); //ビットマップデータのメモリのポインタ
BitCount = bmp->GetPixelFormatSize(bmp->PixelFormat); //画像データのビット数

//輝度値の取得、設定
switch (bmp->PixelFormat){
case Imaging::PixelFormat::Format8bppIndexed:
//8ビットデータの場合

ymin=0;
ymax=0;

for (j = 0; j < rect.Height; j++){
for (i = 0; i < rect.Width; i++){
Bright = pBuf[i + j * bmpData->Stride];//輝度値の取得

//輝度値の設定(二値化)
if (Bright >= Threshold){
pBuf[i + j * bmpData->Stride] = 255;//白に設定}
else{
pBuf[i + j * bmpData->Stride] = 0;//黒に設定}

if(pBuf[i+j * bmpData->Stride] == 255){
if(ymin = 0){ymin = j;}
if(ymax < j){ymax = j;}
}}
y = ymax - ymin;}
break;

//24ビットと32ビットの場合
Step = BitCount / 8;

ymin=0;
ymax=0;

for (j = 0; j < rect.Height; j++){
for (i = 0; i < rect.Width; i++){
//輝度値の取得(略)

//輝度値の設定(二値化)
if (((B >= Threshold) || (G >= Threshold) || (R >= Threshold)){
//白に変換
pBuf[i * Step +j * bmpData->Stride] = 255;//青
pBuf[i * Step+1+j * bmpData->Stride] = 255;//緑
pBuf[i * Step+2+j * bmpData->Stride] = 255;//赤}
else{
//黒に変換
pBuf[i * Step +j * bmpData->Stride] = 0;//青
pBuf[i * Step+1+j * bmpData->Stride] = 0;//緑
pBuf[i * Step+2+j * bmpData->Stride] = 0;//赤}

if((pBuf[i * Step +j * bmpData->Stride] == 255)
&&(pBuf[i * Step+1+j * bmpData->Stride] == 255)
&&(pBuf[i * Step+2+j * bmpData->Stride] == 255))
{
if(ymin = 0){ymin = j;}
if(ymax < j){ymax = j;}
}}
break;

投稿日時 - 2010-06-04 16:27:07

お礼

ImagingSol 様

貴重なご助言,誠にありがとうございます!!いつもWEBを見させていただいております.どれも参考になるものが多く,大変勉強になっています.これからも色々な作品が見れますことを楽しみにしております.また,色々とご助言いただけましたら幸いに思います!

投稿日時 - 2010-06-04 15:58:32

このQ&Aは役に立ちましたか?

7人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

 VC++と言っても画像処理の方法は数多くあるので、具体的にどういう環境で行っているのかが分からないと何も答えられません。
(bmpData->Strideとかいう書き方を見たら、WindowsフォームアプリケーションでBitmapオブジェクトをいじってるように見えますが)

 コードを見る限りでは、i がX座標、j がY座標、Stepが1ピクセルのbyte数を表しているようですから、

> If picturebox1.Point(X, Y) = RGB(255, 255, 255) Then //白があれば



if ((pBuf[x * Step + y * bmpData->Stride]==255)
&& (pBuf[x * Step + 1 + y * bmpData->Stride]==255)
&& (pBuf[x * Step + 2 + y * bmpData->Stride]==255))
{
// 白があれば
}

という感じでしょうか。
 Stepの値が3なら、

Color* pcol = (Color*)(&pBuf[x * Step + y * bmpData->Stride]);
if (*pcol == RGB(255, 255, 255))
{
// 白があれば
}

という感じにもできたかな?

投稿日時 - 2010-06-03 22:47:35

補足

ご助言いただきました内容で解決することができました!!本当にありがとうございました!

投稿日時 - 2010-06-04 16:54:48

お礼

magicalpass 様

懇切丁寧なご助言誠にありがとうございます!また,説明不足な点申し訳ございませんでした.環境はおっしゃられる通り,Windowsフォームアプリケーションでビットマップを画像処理しようとしています.またiはX方向,jはY方向であります.再度検討をしてまいりたいと思います!

投稿日時 - 2010-06-04 15:54:44

あなたにオススメの質問