Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
x軸方向のsobelフィルタのサンプル(C++)
// opencvを使わないプログラム。ただしppm形式の画像を見られるソフトが必要。
// 実行する際は"input.ppm"というファイル名の画像データを用意する。
#include <fstream>
#include <sstream>
#include <string>
#include <stdlib.h>
using namespace std;
void GetImageSize( const char* filename );
void LoadImage( const char* filename, unsigned char* src ); // グレースケールに変換して取得する関数
void SaveImage( const char* filename, const unsigned char* dst );
int g_width; // 入力画像サイズ
int g_height;
int main(){
unsigned char* src = NULL;
unsigned char* dst = NULL;
try{ // 例外処理をおこなうためにtry
GetImageSize( "input.ppm" ); // ヘッダから画像サイズだけ取得
// 取得した画像サイズから配列を確保
src = new unsigned char[ g_width * g_height ]; // 入力用配列
dst = new unsigned char[ g_width * g_height ]; // 出力用配列
LoadImage( "input.ppm", src ); // 入力画像取得
for( int y = 0; y < g_height; ++y ){
for( int x = 0; x < g_width; ++x ){
//=====================この部分を書き換える========================
// ここでは例としてx軸方向のsobelフィルタの処理を記述する
// 配列外アクセスが起こらないように画像端は処理しないことにする。
if( x == 0 || x == g_width - 1 || y == 0 || y == g_height - 1 )
continue;
unsigned char I[ 3 ][ 3 ];
for( int i = 0; i < 3; ++i ){
for( int j = 0; j < 3; ++j ){
// 注目画素と8近傍の値を取得
I[ i ][ j ] = src[ ( y + i - 1 ) * g_width + ( x + j - 1 ) ];
}
}
int temp1, temp2, out;
temp1 = -1 * I[0][0] - 2 * I[1][0] - 1*I[2][0];
temp2 = 1 * I[0][1] + 2 * I[1][1] + 1 * I[2][2];
out = abs( temp1 + temp2 ); // 和の絶対値をとる
out /= 4; // 4で割ることで10bitから8bitに
//=================================================================
dst[ y * g_width + x ] = ( unsigned char )out;
}
}
SaveImage( "output.ppm", dst ); // 出力画像保存
// newした配列を解放
delete[] dst;
dst = NULL;
delete[] src;
src = NULL;
exit( EXIT_SUCCESS );
}catch(...){ // 例外が発生した時はここに処理が移る。
// newした配列の解放
delete[] src;
src = NULL;
delete[] dst;
dst = NULL;
exit( EXIT_FAILURE );
}
return 0;
}
void GetImageSize( const char* filename ){
string buf;
istringstream iss;
ifstream ifs( filename, ios_base::binary );
do{
getline( ifs, buf ); // P6
}while( buf[ 0 ] == '#' ); // コメント読み飛ばし
do{
getline( ifs, buf ); // WIDTH HEIGHT
}while( buf[ 0 ] == '#' ); // コメント読み飛ばし
iss.str( buf );
iss >> g_width; //画像サイズを取得してグローバル変数に格納
iss >> g_height;
}
void LoadImage( const char* filename, unsigned char* src ){
string buf;
ifstream ifs( filename, ios_base::binary );
//=============ヘッダ読み飛ばし=================
for( int i = 0; i < 3; ++i ){
do{
getline( ifs, buf ); // ヘッダはコメントを除くと3行ある
}while( buf[ 0 ] == '#' ); // コメント読み飛ばし
}
//=============================================
for( int i = 0; i < g_width * g_height; ++i ){ // カラー画像からグレースケール画像に変換
char temp;
unsigned char max = 0;
for( int c = 0; c < 3; ++c ){
ifs.read( &temp, 1 );
if( max < static_cast< unsigned char >( temp ) )
max = static_cast< unsigned char >( temp );
}
src[ i ] = max; // RGBのうち最大値を採用する
}
}
void SaveImage( const char* filename, const unsigned char* dst ){
ofstream ofs( filename, ios_base::binary );
//ヘッダ記述
ofs << "P6" << endl;
ofs << g_width << "\t" << g_height << endl;
ofs << "255" << endl;
for( int i = 0; i < g_width * g_height; ++i ){
for( int c = 0; c < 3; ++c ){
ofs << dst[ i ];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.