C言語で画像を平滑化、エッジ抽出を行うプログラムを作成
Posted: 2013年7月06日(土) 21:37
初めまして、jsanymと申します。
大学の授業で 「カメラで撮影した画像を用いて、平滑化ならびにエッジ抽出を作成せよ」といった課題が出されました。
以下のソースコードで私が書いた部分は平滑化とエッジ抽出です。他の部分はあらかじめ用意されていたソースコードです。
一応、コンパイルはできるのですが、処理命令を平滑化にすると「動作は停止しました」となります。エッジ抽出にすると動作は停止しないのですが、
何も起きません。元画像もエッジ抽出されていません。
どこが間違っているかご指摘お願いします。
コンパイラはEasyIDEC Ver0.0.6.0
言語はCです。
C言語は得意ではありません。
大学の授業で 「カメラで撮影した画像を用いて、平滑化ならびにエッジ抽出を作成せよ」といった課題が出されました。
以下のソースコードで私が書いた部分は平滑化とエッジ抽出です。他の部分はあらかじめ用意されていたソースコードです。
一応、コンパイルはできるのですが、処理命令を平滑化にすると「動作は停止しました」となります。エッジ抽出にすると動作は停止しないのですが、
何も起きません。元画像もエッジ抽出されていません。
どこが間違っているかご指摘お願いします。
コンパイラはEasyIDEC Ver0.0.6.0
言語はCです。
C言語は得意ではありません。
//24bitビットマップ画像を処理するプログラム
#include<stdio.h>
#include<stdlib.h>
#define H 320 //画像の縦幅 Height
#define W 240 //画像の横幅 Width
//-----入力関数-------------------------------------------------------
int readImageFile(char filename[], unsigned char bufhead[], unsigned char image[W][H][3])
{
unsigned char buf[W*3];
int i,j,k;
FILE *fp;
if((fp=fopen(filename, "rb")) == NULL){
return 0; //読み込みに失敗した場合0を返す
}
fread(bufhead,54,1,fp); //54Byte分のヘッダ情報を確保しておく
for(j=0;j<H;j++){
fread(buf,W*3,1,fp); //一行分のB,G,R値をbufに格納
for(i=0;i<W;i++){
for(k=0;k<3;k++){
image[i][j][k] = buf[i*3+k]; //一次元配列を三次元配列に分解 (k = 0:B, 1:G, 2:R)
}
}
}
fclose(fp);
return 1; //正常終了した場合1を返す
}
//-----出力関数------------------------------------------------------
int writeImageFile(char filename[], unsigned char bufhead[], unsigned char image[W][H][3])
{
unsigned char buf[W*3];
int i,j,k;
FILE *fp;
if((fp=fopen(filename, "wb")) == NULL){
return 0;
}
fwrite(bufhead,54,1,fp); //入力関数で確保したヘッダ情報をそのまま書き込む
for(j=0;j<H;j++){
for(i=0;i<W;i++){
for(k=0;k<3;k++){
buf[i*3+k] = image[i][j][k]; //三次元配列を一次元配列に格納
}
}
fwrite(buf,W*3,1,fp); //一行分のB,G,R値を書き込む
}
fclose(fp);
return 1;
}
//-----複写---------------------------------------------------------
void copyImage(unsigned char input[W][H][3], unsigned char output[W][H][3])
{
int i,j,k;
for(j=0;j<H;j++){
for(i=0;i<W;i++){
for(k=0;k<3;k++){
output[i][j][k] = input[i][j][k]; //outputにinputをそのまま格納する
}
}
}
}
//----グレースケール化------------------------------------------------
void transformGrayImage(unsigned char input[W][H][3], unsigned char output[W][H][3])
{
int i,j,k;
int temp;
for(j=0;j<H;j++){
for(i=0;i<W;i++){
temp = (input[i][j][0] + input[i][j][1] + input[i][j][2]) / 3; //RGB各値の平均
for(k=0;k<3;k++){
output[i][j][k] = temp;
}
}
}
}
//----単純平滑化------------------------------------------------------
void smoothImage(unsigned char input[W][H][3], unsigned char output[W][H][3])
{
int i,j,k;
int buf;
unsigned char c[9];
for(i=1;i<H-1;i++){
for(j=1;j<W-1;j++){
for(k=0;k<3;k++){
buf = (int)input[i-1][j-1][k]
+ (int)input[i-1][j][k]
+ (int)input[i-1][j+1][k]
+ (int)input[i][j-1][k]
+ (int)input[i][j][k]
+ (int)input[i][j+1][k]
+ (int)input[i+1][j-1][k]
+ (int)input[i+1][j][k]
+ (int)input[i+1][j+1][k];
output[i][j][k] = buf/9;
}
}
}
}
//----エッジ抽出------------------------------------------------------
void edgeImage(unsigned char input[W][H][3], unsigned char output[W][H][3], float amp)
{
static int cx[9] = { 0, 0, 0, /* オペレータの係数x(Roberts) */
0, 1, 0, /* 他のオペレータの時は */
0, 0,-1}; /* 書き換えて下さい */
static int cy[9] = { 0, 0, 0, /* オペレータの係数y(Roberts) */
0, 0, 1, /* 他のオペレータの時は */
0,-1, 0}; /* 書き換えて下さい */
int d[9];
int i, j,k, dat;
float xx, yy, zz;
for (i = 1; i < W-1; i++) {
for (j = 1; j < H-1; j++) {
for(k=0;k<3;k++){
d[0] = input[i-1][j-1][k];
d[1] = input[i-1][j][k];
d[2] = input[i-1][j+1][k];
d[3] = input[i][j-1][k];
d[4] = input[i][j][k];
d[5] = input[i][j+1][k];
d[6] = input[i+1][j-1][k];
d[7] = input[i+1][j][k];
d[8] = input[i+1][j+1][k];
xx = (float)(cx[0]*d[0] + cx[1]*d[1] + cx[2]*d[2]
+ cx[3]*d[3] + cx[4]*d[4] + cx[5]*d[5]
+ cx[6]*d[6] + cx[7]*d[7] + cx[8]*d[8]);
yy = (float)(cy[0]*d[0] + cy[1]*d[1] + cy[2]*d[2]
+ cy[3]*d[3] + cy[4]*d[4] + cy[5]*d[5]
+ cy[6]*d[6] + cy[7]*d[7] + cy[8]*d[8]);
zz = (float)(amp*sqrt(xx*xx+yy*yy));
dat = (int)zz;
if(dat > 255) dat = 255;
output[i][j][k] = (char)dat;
}
}
}
}
//-----メイン文-----------------------------------------------------
int main(void)
{
unsigned char bufhead[54], inputImage[W][H][3], processImage[W][H][3], outputImage[W][H][3];
char inputFileName[100];
char outputFileName[100];
float amp;
int command;
int theta; //しきい値
printf("入力画像 (24bit BMP):"); scanf("%s",&inputFileName);
if((readImageFile(inputFileName, bufhead, inputImage)) == 0){
printf("File load error\n");
return 0;
}
printf("\n 1:複写\n 2:Gray化\n 3:保存\n 4:平滑化\n 5:エッジ抽出 0:終了\n");
do{
printf("\n処理命令:"); scanf("%d",&command);
if(command == 1){
copyImage(inputImage, processImage);
printf("複写しました\n");
}
if(command == 2){
transformGrayImage(inputImage, processImage);
printf("Gray化しました\n");
}
if(command == 4){
smoothImage(inputImage, processImage);
printf("平滑化しました\n");
}
if(command == 5){
edgeImage(inputImage,processImage, amp);
printf("エッジ抽出しました\n");
}
if(command == 3){
copyImage(processImage,outputImage);
printf("\n出力画像 (24bit BMP):"); scanf("%s",&outputFileName);
if((writeImageFile(outputFileName, bufhead, outputImage)) == 0){
printf("File save error\n");
return 0;
}
}
copyImage(processImage, inputImage); //次の処理のため、処理した画像をinputImageに複写
}while(command != 0);
return 0;
}