これからの季節に親子でハイキング! >>

C++言語で線形補間法のプログラムを組んで実行しているのですが、どしてもうまくいきません。ただ2倍の画像を作っているだけなのですが・・・。
以下プログラムを載せます、おおよその場所はわかるのですがどうすれば通るのかわかりません。どう直したらよいのか分かる方がいましたらご教授お願いします。
※bmp[0]:現画像 pic:bmp[0]の縦横2倍の画像

// 線形補間法 //
int zx = 2;
int zy = 2;
int i,j,m,n;
float x,y,p,q;
int xs = bmp[0]->Width/2;
int ys = bmp[0]->Height/2;
int d;

for(i = -ys; i < ys; i++){
for(j = -xs; j < xs; j++){
y = i/zy;
x = j/zx;
if(y > 0){
m = (int)y;
}else{
m = (int)(y-1);}
if(x > 0){
n = (int)x;
}else{
n = (int)(x-1);}
q = y - m;
p = x - n;
if(q == 1){q = 0; m = m + 1;}
if(p == 1){p = 0; n = n + 1;}
if((m >= -ys)&&(m < ys)&&(n >= -xs)&&(n < xs)){
d = (int)((1.0 - q) * (1.0 - p) * (bmp[0]->GetPixel( m + ys, n + xs)) //おそらくこの辺に問題があるかと思われます。
+ p * (bmp[0]->GetPixel( m +ys, n + xs))
+ q * (1.0 - p) * (bmp[0]->GetPixel(m + 1 + ys, n + xs))
+ p * (bmp[0]->GetPixel(m + 1 + ys, n + 1 + xs)));
}else{
d = 0;
}
if(d < 0){d = 0;}
if(d > 255){d = 255;}
pic->SetPixel(i + ys, j + xs) = d;
}
}

pictureBox2->Image = pic;
}

A 回答 (4件)

> そうすると最初にグレースケール化が必要になるのでしょうか?


> どこを見てもそんなことは書いてないのですが、どこにでもある
> このプログラムのimage_in[ ][ ]とはどういうことなのでしょう

さ~ 私には分りません
あなたのお使いの環境すら知らないのですから

当方はWindows環境で行っています
元画像がグレースケールなら グレースケール化する必要がない場合もあるでしょう
グレースケールでも8階調、256階調、65536階調などその方法は沢山あります
これをメモリー上に取り込むのも環境によってさまざまだと思います
Unix系のXの上とか、Windows上とか DOSのG-RAMを直接いじってるとか

この i,jのループの中で x,yがどのような値になるのか机上で計算してみましょう

COLORREF cl[4]d ,d;
cl[0] = bmp[0]->GetPixel( n + xs + 0, m + ys + 0 );
cl[1] = bmp[0]->GetPixel( n + xs + 1, m + ys + 0 );
cl[2] = bmp[0]->GetPixel( n + xs + 0, m + ys + 1 );
cl[3] = bmp[0]->GetPixel( n + xs + 1, m + ys + 1 );

といった具合に取得して
d.r = (int)(1.0 - q) * (1.0 - p) * cl[0].r
+ p * cl[1].r
+ q * (1.0 - p) * cl[2].r
+ p * cl[3].r;
d.g = (int)(1.0 - q) * (1.0 - p) * cl[0].g
+ p * cl[1].g
+ q * (1.0 - p) * cl[2].g
+ p * cl[3].g;
d.b = (int)(1.0 - q) * (1.0 - p) * cl[0].b
+ p * cl[1].b
+ q * (1.0 - p) * cl[2].b
+ p * cl[3].b;

pic->SetPixel( i + xs, j + ys, d );
といった具合で設定しますが

SetPixel/GetPixelなどはコストの高いメソッドなのでほとんど使いません
数点の点の描画などなら使いますが ・・・

WindowsならBITMAPオブジェクトからGetBitmapBitsなどを使ってデータを取得して
その上で配列操作を行います
    • good
    • 0
この回答へのお礼

Color color1 = bmp[0]->GetPixel(m + ys, n + xs);
r1 = color1.R; g1 = color1.G; b1 = color1.B;
Color color2 = bmp[0]->GetPixel(m + ys, n + xs);
r2 = color2.R; g2 = color2.G; b2 = color2.B;
Color color3 = bmp[0]->GetPixel(m + 1 + ys, n + xs);
r3 = color3.R; g3 = color3.G; b3 = color3.B;
Color color4 = bmp[0]->GetPixel(m + 1 + ys, n + 1 + xs);
r4 = color4.R; g4 = color4.G; b4 = color4.B;

r = (int)(((1.0 - q) * (1.0 - p) * r1) + (p * r2) + (q * (1.0 - p) * r3) + p * r4);
g = (int)(((1.0 - q) * (1.0 - p) * g1) + (p * g2) + (q * (1.0 - p) * g3) + p * g4);
b = (int)(((1.0 - q) * (1.0 - p) * b1) + (p * b2) + (q * (1.0 - p) * b3) + p * b4);
}else{
r = 0; g = 0; b = 0;

}
if(r < 0){r = 0;}
if(g < 0){g = 0;}
if(b < 0){b = 0;}
if(r > 255){r = 255;}
if(g > 255){g = 255;}
if(b > 255){b = 255;}

Color newColor = Color::FromArgb( r, g, b );
pic->SetPixel(i + ys * 2, j + xs * 2, newColor );
}
教えてもらったことと同じような感じですが、上記のようにやってみた結果うまくいきました。ありがとうございます。

それと、(m >= -ys)&&(m < ys - 1)&&(n >= -xs)&&(n < xs - 1)の部分なのですが、-1とは何のことだったのでしょう?
線形補間された画像の右と下に線があわられてしまいました。(_|のような感じ) -1を消したら何もでなくなりましたが。

SetPixel/GetPixel以外にも画素配置の方法があるということなので、調べてみます。本当にありがとうございました。

お礼日時:2008/12/17 18:00

(m >= -ys)&&(m < ys - 1)の ys-1は



4ピクセルのデータを収集する際の右上と右下の +1する分を考慮しないと画素のない部分を指示してしまうためです

たとえば 120x120の大きさだった場合に
120,0 が左上だった場合 そのままだと
120,0 121,0
120,1 121,1
の4ピクセルを拾うことになりますが 実際には 121といったX座標がないためライブラリーがどこからデータを拾ってくるか分りません
エラーになってくれればまだいいのですが ・・・
    • good
    • 0

dの数式はこのままでいいと思います


ループの i,jの範囲と SetPixelに与える座標のオフセットが問題なのではないかと思います

for ( i = -ys * 2; i < ys * 2; i++ ) {
  for ( j = -xs * 2; j < xs * 2; j++ ) {
    // xypqmnの演算
    if((m >= -ys)&&(m < ys -1)&&(n > -xs)&&(n < xs - 1)){
      // dの演算
    } esle {
      d = 0
    }
    pic->SetPixel( i + ys * 2, j * xs * 2 ) = d;
  }
}
といった具合でしょう
    • good
    • 0
この回答へのお礼

私のプログラムだと画像を2枚用意しているから2倍しているんですね。
エラーGetPixelとSetPixelの部分で、それぞれ"class に対して正しくありません。"と"関数に 2 個の引数を指定できません。"といったエラーなのですがよく考えてみたらGet(set)Pixel関数は座標指定された場所のRGBの3つデータをもらうわけですから、掛け算ができないのは当たり前です。しかし、そうすると最初にグレースケール化が必要になるのでしょうか?どこを見てもそんなことは書いてないのですが、どこにでもあるこのプログラムのimage_in[ ][ ]とはどういうことなのでしょう?

//c言語線形補間法プログラム//
#include "Params.h"

image_in; 入力画像
image_out; 出力画像
zx; (拡大率)横
zy; (拡大率)縦

void(~){
int i,j,m,n;
float x,y,p,q;
int xs = X_SIZE/2;
int ys = Y_SIZE/2;
int d;

for(i = -ys; i < ys; i++){
for(j = -xs; j < xs; j++){
y = i/zy;
x = j/zx;
if(y > 0){
m = (int)y;
}else{
m = (int)(y-1);}
if(x > 0){
n = (int)x;
}else{
n = (int)(x-1);}
q = y - m; 
p = x - n;
if(q == 1){q = 0; m = m + 1;}
if(p == 1){p = 0; n = n + 1;}
if((m >= -ys)&&(m < ys)&&(n >= -xs)&&(n < xs)){
d = (int)((1.0 - q) * (1.0 - p) * image_in[m + ys][n + xs]
+ p * image_in[m + ys][n + 1 + xs]
+ q * (1.0 - p) * image_in[m + 1 + ys][n + xs]
+ p * image_in[m + 1 + ys][n + 1 + xs]);
}else{
d = 0;
}
if(d < 0){d = 0;}
if(d > 255){d = 255;}
image_out[i + ys][j + xs] = d;
}
}
}

お礼日時:2008/12/11 19:12

何に困っているのでしょう?



このままだと 元画像の中心部分を2倍に伸張して『描画領域は同じ大きさ』で描画するのだと思いますが ・・・
    • good
    • 0
この回答へのお礼

線形補間法を使って画像のリサイズ(ここでは2倍)をするのが目的です。
最近傍法より滑らかになる画像が出力されるとのことなのでこちらを使っています。
bmp[0]には100*100pixelの画像が格納されていて、picには200*200pixelの画像が格納されています。それで拡大率であるzx(横),zy(縦)を2倍にして縦横2倍の画像(pic)を作ろうとしています。

お礼日時:2008/12/10 15:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q線形補間

線形補間での求め方
問題文:
1.数値を読み込む
2.xを読み込む
3.x<x1 または x>xnならエラー
3.x1<x<i+1 となるiを見つける
4.補間公式でyを求める
5.結果をプリントする

#include<stdio.h>
float hokan(void);
int xn[] = {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75};
double yn[] = {0.000,0.087,0.173,0.258,0.342,0.422,0.500,0.573,
0.624,0.707,0.766,0.819,0.866,0.906,0.939,0.965};
int x=5;
void main()
{
printf("y = %lf\n", hokan());
}
float hokan(void)
{
int i;
double y;

if(x <0|| 75<= x){
printf("エラーです\n");
}
else{
for(i=0; xn[i] < x; i++)
y = (yn[i+1] - yn[i]) * (x - xn[i]) / (xn[i+1] - xn[i]) + yn[i];
return y;
}
}

数表を最初にxnとynで表記しています。
このプログラムで線形補間が行われてないそうなのですが・・
何か誤りがある様でしたらどなたか教えてください。

線形補間での求め方
問題文:
1.数値を読み込む
2.xを読み込む
3.x<x1 または x>xnならエラー
3.x1<x<i+1 となるiを見つける
4.補間公式でyを求める
5.結果をプリントする

#include<stdio.h>
float hokan(void);
int xn[] = {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75};
double yn[] = {0.000,0.087,0.173,0.258,0.342,0.422,0.500,0.573,
0.624,0.707,0.766,0.819,0.866,0.906,0.939,0.965};
int x=5;
void main()
{
printf("y = %lf\n", hokan());
}
float hokan(...続きを読む

Aベストアンサー

>数表を最初にxnとynで表記しています。
>このプログラムで線形補間が行われてないそうなのですが・・

 どなたかに言われたのですか?。

 その方は、x = 5; と「数表」にある既知の値(線形補間不要)を用いているから、そのことを揶揄して言ったのでは・・。
 
☆ご自分で、「数表」にない値(例えば、x = 3 )で実行し、電卓での結果と比較してみては如何でしょう。

Q直線補間出来る関数

直線補間できる関数はエクセルに有るのでしょうか?
直線補間とはxy座標において、点A(x1,y1),点B(x2,y2)が有ったときに、x1≦x≦x2における任意のxに対するyの値を点AB間が直線だと仮定して求めるすることです。

今は、VLOOKUP,match,Index関数を使ってやってますが、関数がある非常に楽です。

Aベストアンサー

 2点だけでしたら使うまでも無い様な気がしますが、FORECAST関数というものがあります。

【参考URL】
 FORECAST 関数 - Excel - Office.com
  http://office.microsoft.com/ja-jp/excel-help/HP010342532.aspx

 初心者のエクセル(Excel)学習・入門 > エクセル関数の使い方 > 統計関数 > FORECAST関数とは
  http://excel.onushi.com/function/forecast.htm

Q直線補間について

#define N 8
double x[N]={0,10,11,15,20,30,50,100},
y[N]={0, 0, 5,10,13,11, 8, 6};
といったデータ(実験で得られたデータです。)について任意のx座標tにおけるy座標を直線補間で求めたいのですが、この場合、0<t<10,10<t<11,......50<t<100と場合分けして直線の式を求める方法しか思いつかないのですが、この場合、実験で得られたデータの数の増減によってプログラムも毎回作り直さないといけないので困っております。もしこの方法以外に良い方法があれば教えてください。ソースも教えて頂けると有難いです。

Aベストアンサー

malloc()
という関数があります.
これは動的にメモリを確保する関数です.
よく使います.
これをつかうと,「Cらしいプログラム」になります.

まず,データの数を入力して,それに見合うメモリを動的に確保します.そして,大きい順に並べ替えをして,
あとは直線補間することになるでしょう.

下記の様なイメージでしょうか.
デバッグしてないので,あくまでイメージです.

int N;
double *x,*y;

fscanf("%d",&N);
if((p1=malloc(N*sizeof(double)))==NULL){
fprintf(stderr,"can't allocate system memoey [%d]\n",N*sizeof(double));
exit(1);
}
if((p2=malloc(N*sizeof(double)))==NULL){
fprintf(stderr,"can't allocate system memoey [%d]\n",N*sizeof(double));
exit(1);
}

x=(double *)p1;
y=(double *)p2;
for(i=0;i<N;i++){
fscanf("%lf %lf",&(x[i]),&(y[i]));
}

sort(x,y);// データを大きさによってソートするルーチン

// 直線補間ルーチン
// 区間による場合分け.

それでは.

malloc()
という関数があります.
これは動的にメモリを確保する関数です.
よく使います.
これをつかうと,「Cらしいプログラム」になります.

まず,データの数を入力して,それに見合うメモリを動的に確保します.そして,大きい順に並べ替えをして,
あとは直線補間することになるでしょう.

下記の様なイメージでしょうか.
デバッグしてないので,あくまでイメージです.

int N;
double *x,*y;

fscanf("%d",&N);
if((p1=malloc(N*sizeof(double)))==NULL){
fprintf(stderr,"can't ...続きを読む

Q画像の拡大・縮小

読み込んだ画像を1.5倍に拡大、2/3倍に縮小したいのですが、C言語でそのようなことは可能なのですか?また、できるとしたら、どのように行えばいいのでしょうか?教えてくださいm(_ _)m

Aベストアンサー

座標系だけでしたら処理は単純です。
単に倍率をかけてあげればよいだけです。

具体的な計算式は、
(1.5倍の例)
 Image( x*1.5, y*1.5 ) = Image( x, y )
ということです。

これだけでは多分わからないですね^_^;
以下にプログラムを書きます。

----------------------------------------------------------------

void main()
{
 unsinged char Image[ 16 ][ 16 ]; // 読み込んだ画像の格納場所
 unsinged char Image2[ 24 ][ 24 ]; // 拡大した画像の格納場所
 double zoom = 1.5;
 int x, y;
 int i, j;

/*
  画像の読み込み処理
*/

 for(x=0; x<16; x++)
 {
  for(y=0; y<16; y++)
  {
   // 拡大した時に隙間が空くので、その箇所を補完する
   for(i=0; (double)i<zoom; i++)
   {
    for(j=0; (double)j<zoom; j++)
    {
     Image2[ (int)(x*zoom)+i ][ (int)(y*zoom)+j ] = Image[ x ][ y ];
    }
   }
  }
 }
}

----------------------------------------------------------------

これでImage2に1.5倍した画像が格納されるはずです。
(注:Image2の配列のサイズは任意に決めています)

理解できたでしょうか。

画像の拡大縮小に関しては、まだ多くの手法が存在しますので、
調べてみると面白いかもしれませんよ(^_^)

座標系だけでしたら処理は単純です。
単に倍率をかけてあげればよいだけです。

具体的な計算式は、
(1.5倍の例)
 Image( x*1.5, y*1.5 ) = Image( x, y )
ということです。

これだけでは多分わからないですね^_^;
以下にプログラムを書きます。

----------------------------------------------------------------

void main()
{
 unsinged char Image[ 16 ][ 16 ]; // 読み込んだ画像の格納場所
 unsinged char Image2[ 24 ][ 24 ]; // 拡大した画像の格納場所
 double zoom = 1.5...続きを読む

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

QGetPrivateProfileStringでiniファイル読込む処理を詳しく知りたいのですが・・・

お世話になっています。

iniファイルを読込み、各変数に代入するC言語のDLLを作成したいのです。
このサイトの投稿や、MSDNなどにも載っていたのですが、
少し理解に苦しみます。

現在まで、理解した点がwindows.hのインクルードを
記述するところ辺りです。
iniファイルは下記のようなレイアウトです。

---<mst.ini>----------------------------
[user]
name=username
ID=userid
[pc]
pcname=FMV
----------------------------------------

#include<windows.h>は記述することまでは
分かりましたが、以下から進みません。。。

GetPrivateProfileString("")

初心者で申し訳ありませんが、お助け願います。

Aベストアンサー

こんにちは。itohhといいます。

サンプルを載せておきます。

mst.iniファイル内の[user]セクションのnameキーの値を取得する。
DWORD dwLen=0;
char strBuf[100];
dwLen = GetPrivateProfileString("user",       // セクション名
                "name",       // キー名
                "soushi_ni",     // デフォルト値
                strBuf,       // 読み込んだ値を格納するエリア
                sizeof(strBuf),   // 上記のエリアのサイズ
                "mst.ini" );     // iniファイル名

解説:
iniファイル名をフルパスで指定しないとWindowsのディレクトリにあるものと判断されます。
Win9xなら「c:\windows」、WinNT系なら「c:\WinNT」。

[user]セクションのnameキーがないときは、デフォルト値で指定した値が設定させます。

復帰値「dwLen」は実際に設定した値(文字列)の長さが返されます。

こんにちは。itohhといいます。

サンプルを載せておきます。

mst.iniファイル内の[user]セクションのnameキーの値を取得する。
DWORD dwLen=0;
char strBuf[100];
dwLen = GetPrivateProfileString("user",       // セクション名
                "name",       // キー名
                "soushi_ni",     // デフォルト値
                strBuf,       // 読み込んだ値を格納するエリア
             ...続きを読む

Q実行途中でのエラー発生について

こんばんは。
この掲示板を頻繁に利用させていただいている者です。

Visual C++.NET 2003を利用しソケットプログラミングをしていたところ、突然わけの分からないエラーが途中で発生してしまいます。

[エラー内容]
Debug Assertion Failed!
File: fprintf.c
Line:56

Expression: str != NULL

For information on how your program can cause an assertion failure,see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
上記のようなエラー内容です。

今まで実行可能であったのに、突然エラーメッセージが発生しました。
Line:56ということから56行目を見たところ、str != NULLという記述もしていませんし、かつその行はコメントを記述しています。

なにか原因があるのでしょうか?

よろしくお願いします。

こんばんは。
この掲示板を頻繁に利用させていただいている者です。

Visual C++.NET 2003を利用しソケットプログラミングをしていたところ、突然わけの分からないエラーが途中で発生してしまいます。

[エラー内容]
Debug Assertion Failed!
File: fprintf.c
Line:56

Expression: str != NULL

For information on how your program can cause an assertion failure,see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
上記のようなエラー内容です。

今ま...続きを読む

Aベストアンサー

> File: fprintf.c
> Line:56

これは、fprintf関数のソースの56行目です。
質問者さんのプログラムで、fprintf関数を呼び出ししている箇所があると思います。

VCは現在手元にありませんが、[表示]メニューから「コールスタック」ウィンドウを表示すると、どういう関数が順番に呼ばれてfprintfのところにたどり着いたかをあらわすコールスタックが表示されます。
呼び出し先(上)から遡って、自身の作成したモジュールの所での引数を確認してみてください。

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

QC言語での平滑化フィルタ

OPenCVを使わずにC言語で3×3の平滑化フィルタを作成したと思っています。
それで、プログラム例を参考にして作ろうと、googleなどで検索しているのですけれども、なかなかファイルの読み込みから平滑化処理まで全てを書いてくれているプログラム例が見つかりません。
もしご存知の方がいらしたら、コンパイル可能な状態のプログラム例を教えて頂けないでしょうか?
環境はwindows VISTAでVisual Studio2008を使っています。
画像サイズなどはこだわりません。

Aベストアンサー

 こんばんは。
 取りあえず読み込み元がDIB24bit前提と言う事で。グレースケールに変換しながら計算しています。全てを9で割って足さず、全て足してから9で割っています。若しかしたら、間違っているかもしれませんが、其処は御勘弁下さい。

#include<windows.h>
#include<tchar.h>

//固定長配列を数える
#define ArrayCount(a) (sizeof(a) / sizeof(a[0]))

//プロパティ名
const LPCTSTR TSTR_BITMAP = TEXT("bitmap");

//色彩の構造
struct Colors
{
long R;
long G;
long B;
};

//グレースケール変換
static long GetY(long R, long G, long B)
{
return 0.298912 * R + 0.586611 * G + 0.114478 * B;
}

//色彩を設定する
static void SetColor(VOID* p, int x, int y, int strideByte, const Colors* pcolors)
{
BYTE* pByte = (BYTE*)p;
const int pos = (x * 3) + (strideByte * y);
pByte[pos] = pcolors->B;
pByte[pos + 1] = pcolors->G;
pByte[pos + 2] = pcolors->R;
}

//色彩を取り出す
static const Colors GetColor(const VOID* p, int x, int y, int strideByte)
{
const BYTE* pByte = (BYTE*)p;
const int pos = (x * 3) + (strideByte * y);
const Colors colors = {pByte[pos + 2], pByte[pos + 1], pByte[pos]};
return colors;
}

//1スキャン辺りのバイト長を4のn倍調整で計算
static DWORD CalcScanLineByte(const DWORD w, const DWORD bpp)
{
return ((((bpp * w) + 31) / 32) * 4);
}

//範囲外確認
static bool IsInRect(const POINT* ppt, int width, int height)
{
return ppt->x >= 0 && ppt->y >= 0 && ppt->x < width && ppt->y < height;
}

//近傍の計算
static const Colors CalcFilter(const VOID* p, int x, int y, int width, int height, int strideByte)
{
const POINT point[] =
{
{x - 1, y - 1}, {x, y - 1}, {x + 1, y - 1},
{x - 1, y}, {x, y}, {x + 1, y},
{x - 1, y + 1}, {x, y + 1}, {x + 1, y + 1}
};
const int KERNEL_SIZE = ArrayCount(point);
Colors result = {0};
for(int k = 0; k < KERNEL_SIZE; ++k)
{
//範囲外にはみ出た時は、着眼点(中心)の色彩を取る
const int pos = ::IsInRect(&point[k], width, height) ? k : KERNEL_SIZE / 2;
const Colors colors = ::GetColor(p, point[pos].x, point[pos].y, strideByte);
const long Y = ::GetY(colors.R, colors.G, colors.B);
result.R += Y;
result.G += Y;
result.B += Y;
}

//全部足してから9で割る
result.R /= KERNEL_SIZE;
result.G /= KERNEL_SIZE;
result.B /= KERNEL_SIZE;

return result;
}

//滑らかにする
static void Softness(HBITMAP hBitmap, int count = 1/*この数だけ繰り返す*/)
{
BITMAP bitmap = {0};
::GetObject(hBitmap, sizeof(bitmap), &bitmap);

const int strideByte = ::CalcScanLineByte(bitmap.bmWidth, 24);

for(int i = 0; i < count; ++i)
{
for(int y = 0; y < bitmap.bmHeight; ++y)
{
for(int x = 0; x < bitmap.bmWidth; ++x)
{
const Colors colors = ::CalcFilter(bitmap.bmBits, x, y, bitmap.bmWidth, bitmap.bmHeight, strideByte);
::SetColor(bitmap.bmBits, x, y, strideByte, &colors);
}
}
}
}

//ウィンドウクラス登録
static ATOM Regist(LPCTSTR szClassName, WNDPROC wndProc)
{
WNDCLASSEX wndclass = {sizeof(wndclass)};
wndclass.hCursor= ::LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon= NULL;
wndclass.lpszMenuName= NULL;
wndclass.lpszClassName= szClassName;
wndclass.hbrBackground= (HBRUSH)::GetStockObject(WHITE_BRUSH);
wndclass.hInstance= ::GetModuleHandle(NULL);
wndclass.style= 0;
wndclass.lpfnWndProc= wndProc;
wndclass.cbClsExtra= 0;
wndclass.cbWndExtra= 0;
return ::RegisterClassEx(&wndclass);
}

//ウィンドウを作成して開く
static HWND OpenWindow(LPCTSTR szClassName, LPCTSTR szTitleName, INT w, INT h)
{
HINSTANCE hInst = ::GetModuleHandle(NULL);

HWND hWnd = ::CreateWindowEx(WS_EX_TOOLWINDOW, szClassName, szTitleName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT, w, h,
NULL, NULL,
hInst, NULL);
return hWnd;
}

//ウィンドウが作られた
static LRESULT OnCreate(HWND hWnd)
{
HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, TEXT("test.bmp")/*読み込みたいファイル名を入れる*/, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
::Softness(hBitmap, 1);
::SetProp(hWnd, TSTR_BITMAP, hBitmap);
return 0;
}

//xボタン
static LRESULT OnClose(HWND hWnd)
{
HBITMAP hBitmap = (HBITMAP)::GetProp(hWnd, TSTR_BITMAP);
::DeleteObject(hBitmap);
::RemoveProp(hWnd, TSTR_BITMAP);
::DestroyWindow(hWnd);
return 0;
}

//ウィンドウが無くなった
static LRESULT OnDestroy(HWND hWnd)
{
::PostQuitMessage(0);
return 0;
}

//再描画
static LRESULT OnPaint(HWND hWnd)
{
HBITMAP hBitmap = (HBITMAP)::GetProp(hWnd, TSTR_BITMAP);
BITMAP bitmap = {0};
::GetObject(hBitmap, sizeof(bitmap), &bitmap);
HDC hDC = ::CreateCompatibleDC(NULL);
::SelectObject(hDC, hBitmap);
PAINTSTRUCT ps;
HDC hPaint = ::BeginPaint(hWnd, &ps);
::BitBlt(hPaint, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hDC, 0, 0, SRCCOPY);
::EndPaint(hWnd, &ps);
::DeleteDC(hDC);
return 0;
}

LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE: return ::OnCreate(hWnd);
case WM_CLOSE: return ::OnClose(hWnd);
case WM_DESTROY: return ::OnDestroy(hWnd);
case WM_PAINT: return ::OnPaint(hWnd);
}
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hInstancePrev, LPSTR lpCmdLine, int nShowCmd)
{
MSG msg;
TCHAR tstrClassName[] = TEXT("test resize frame");
TCHAR tstrTitleName[] = TEXT("title");

//ウィンドウクラスの登録
::Regist(tstrClassName, &::WndProc);

//ウィンドウを作成して開く
HWND hWnd = ::OpenWindow(tstrClassName, tstrTitleName, 800, 600);

//ウィンドウの表示
::ShowWindow(hWnd, SW_SHOW);

//メッセージ回転
while(::GetMessage(&msg, NULL, 0, 0) == TRUE)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

//終了
return msg.wParam;
}

 こんばんは。
 取りあえず読み込み元がDIB24bit前提と言う事で。グレースケールに変換しながら計算しています。全てを9で割って足さず、全て足してから9で割っています。若しかしたら、間違っているかもしれませんが、其処は御勘弁下さい。

#include<windows.h>
#include<tchar.h>

//固定長配列を数える
#define ArrayCount(a) (sizeof(a) / sizeof(a[0]))

//プロパティ名
const LPCTSTR TSTR_BITMAP = TEXT("bitmap");

//色彩の構造
struct Colors
{
long R;
long G;
long B;
};

//...続きを読む

Qヒストグラム均等化処理プログラム

どなたか以下のヒストグラム均等化処理プログラムを解説して頂けないでしょうか。特にgetMinMax関数とgetHistEqu関数で、何がしたいのか訳がわかりません。
以下のプログラムは、ヒストグラム均等化処理部分のみですが、分かる範囲でいいので、解説お願いします。
-------------------------------------------------------
// ヒストグラム均等化による画素値の割り当てを決定する
// hist:入力画像のヒストグラム
// min:割り当てられる画素値の最小
// max:割り当てられる画素値の最大
// たとえば,min[5]=4 max[5]=6の場合,画素値5には4-6の範囲に割り当てられる
// pixs_min:最小値が割り当てられる画素数
// pixs_max:最大値が割り当てられる画素数
// ave:各画素値に割り当てられる画素数
//★★特にmin,max,pixs_min,pixs_maxの説明の意味が分からないのです。
int getMinMax(int *hist,int *min,int *max,int *pixs_min,int *pixs_max,int ave)
{
int i;
int rest;
int now;
int pixels;
int a,b;

rest=0;
now=0;
for(i=0;i<256;i++) {
pixels=rest+hist[i];
min[i]=now;
if(rest>0) pixs_min[i]=ave-rest;
else pixs_min[i]=ave+100;
a=pixels/ave;
rest=pixels%ave;
max[i]=now+a;
if(rest>0) pixs_max[i]=rest;
else pixs_max[i]=ave+100;
now+=a;
}
for(i=0;i<255;i++) {
if(min[i]>255) min[i]=255;
if(max[i]>255) max[i]=255;
}
max[255]=255;
pixs_max[255]=ave*10;
}

// ヒストグラム均等化による画素値の決定
// 割り当てられる画素値の最小,最大の間で順番に割り当てていく
// ただし,最小,最大については割り当てる画素数に制限がある
int getHistEqu(int x,int *now,int *min,int *max,int *pix_min,int *pix_max)
{
int res;

if(now[x]==max[x]) {
if(pix_max[x]<=0) now[x]=min[x];
else pix_max[x]--;
}
if(now[x]==min[x]) {
if(pix_min[x]<=0) now[x]=min[x]+1;
else pix_min[x]--;
}
if(now[x]>max[x]) now[x]=min[x];
res=now[x];
now[x]++;
return res;
}

int effect(ImageData *img,ImageData *outimg)
{
int x,y;
int rr,gg,bb;
int ro,go,bo;
int i;
int val;
int ave;
int histR[256],histG[256],histB[256];// ヒストグラム
int omaxR[256],omaxG[256],omaxB[256];// 変換後,割り当てられる画素値の最小
int ominR[256],ominG[256],ominB[256];// 変換後,割り当てられる画素値の最大
int pix_maxR[256],pix_maxG[256],pix_maxB[256];// 最小値が割り当てられる画素数
int pix_minR[256],pix_minG[256],pix_minB[256];// 最大値が割り当てられる画素数
int onowR[256],onowG[256],onowB[256];// 次に割り当てる画素値
Pixel pix;

for(i=0;i<256;i++) {
histR[i]=histG[i]=histB[i]=0;
}
ave= img->height * img->width /256; // 画像の全画素数/画素値の範囲
// ヒストグラム作成
for(y=0;y<img->height;y++) {
for(x=0;x<img->width;x++) {
getPixel(img,x,y,&pix);//画像上の画素情報を取得
rr=pix.r;
gg=pix.g;
bb=pix.b;
histR[rr]++;
histG[gg]++;
histB[bb]++;
}
}
// 画素値の割り当て決定
getMinMax(histR,ominR,omaxR,pix_minR,pix_maxR,ave);
getMinMax(histG,ominG,omaxG,pix_minG,pix_maxG,ave);
getMinMax(histB,ominB,omaxB,pix_minB,pix_maxB,ave);
for(i=0;i<256;i++) {
onowR[i]=ominR[i];
onowG[i]=ominG[i];
onowB[i]=ominB[i];
}
// ヒストグラム均等化処理
for(y=0;y<img->height;y++) {
for(x=0;x<img->width;x++) {
getPixel(img,x,y,&pix);//画像上の画素情報を取得
ro=pix.r;
go=pix.g;
bo=pix.b;
rr=getHistEqu(ro,onowR,ominR,omaxR,pix_minR,pix_maxR);
gg=getHistEqu(go,onowG,ominG,omaxG,pix_minG,pix_maxG);
bb=getHistEqu(bo,onowB,ominB,omaxB,pix_minB,pix_maxB);
pix.r=rr;
pix.g=gg;
pix.b=bb;
setPixel(outimg,x,y,&pix);// 画像に値をセットする
}
}
return 0;
}

どなたか以下のヒストグラム均等化処理プログラムを解説して頂けないでしょうか。特にgetMinMax関数とgetHistEqu関数で、何がしたいのか訳がわかりません。
以下のプログラムは、ヒストグラム均等化処理部分のみですが、分かる範囲でいいので、解説お願いします。
-------------------------------------------------------
// ヒストグラム均等化による画素値の割り当てを決定する
// hist:入力画像のヒストグラム
// min:割り当てられる画素値の最小
// max:割り当てられる画素値の最大
// たとえ...続きを読む

Aベストアンサー

例えば、解像度が256×256だったとすると、
ヒストグラム均等化処理後は、各輝度値を持つ画素数は全て256ピクセルになる、ということです。

ここで、入力の輝度値のヒストグラムが
0: 600ピクセル
1: 600ピクセル
2: 600ピクセル
(以下略)
だったとしましょう。

変換後の各輝度値は256ピクセルしかおけませんから、
入力の輝度値0の600ピクセル中、256ピクセルは出力輝度値0、256ピクセルは出力輝度値1、88ピクセルは出力輝度値2になります。

入力の輝度値1に付いては、168ピクセル(入力輝度値0が使った残り)が出力輝度値2、256ピクセルが出力3、176ピクセルが出力4になります。

入力の輝度値2に付いては、80ピクセルが出力輝度値4、256ピクセルが出力5、256ピクセルが出力6、8ピクセルが出力7になります。

と、こういう割当ピクセル数を計算するのが getMinMax ですね。

この場合、
min[0]=0, max[0]=2, pix_min[0]=256, pix_max[0]=88
min[1]=2, max[1]=4, pix_min[1]=168, pix_max[1]=176
min[2]=4, max[2]=7, pix_min[2]= 80, pix_max[2]= 8
という結果になります。

この計算結果を基に、入力輝度値から出力輝度値を算出するのが getHistEqu です。
可能なピクセル数の範囲で、min[x]~max[x]を順番に出力していきます。
例えば、、入力輝度値が2の場合、min[2]=4, max[2]=7ですから
入力輝度値2が出てくる度に、4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, …
と、4~7を順番に出力していきます。
ただし、7を8回出力したところで、出力7のピクセル数は使い切ってますから、
以降は、4, 5, 6, 4, 5, 6, … となり、
4を80回出力した所で、出力4のピクセル数は使い切るので、
以降は 5, 6, 5, 6, …という出力になります。

例えば、解像度が256×256だったとすると、
ヒストグラム均等化処理後は、各輝度値を持つ画素数は全て256ピクセルになる、ということです。

ここで、入力の輝度値のヒストグラムが
0: 600ピクセル
1: 600ピクセル
2: 600ピクセル
(以下略)
だったとしましょう。

変換後の各輝度値は256ピクセルしかおけませんから、
入力の輝度値0の600ピクセル中、256ピクセルは出力輝度値0、256ピクセルは出力輝度値1、88ピクセルは出力輝度値2になります。

入力の輝度値1に付いては、168ピクセル(入力輝度値0が...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング