|
2011/10/04 19:03
夏休みに作ったプログラム達
判別分析法と誤差拡散法は未完成
前回晒したプログラムはインデント直したけど今回は行数が莫大なためもう知りません^q^
グレースケール変換のとこですが計算精度が若干悪いので自分で修正してください。
未完成部分の原因として考えられるのが
判別分析法は画像のサイズによってオーバーフローを起こすためバグる
誤差拡散法は誤差拡散した後、誤差の値を代入する際unsigned char型のため負の数、256以上になるとバグる
という点が考えられるけども、まぁなんか使う機会ある人は自力で直して使ってちょ
あ、ちなみにこれopenCV2.2使ってるんでビルドしたい人はダウソしてこないと使用不可
ちなみにVisualC++
途中配列の部分汚くなってるけど自分のVisualStudioの設定に合わせてあるので勘弁
直す気はない
main.cppはいらないよね
クラス化とか関数の使い方とかは自分で考えてくれ
//判別分析法による閾値決定
unsigned char dam::otsu(Mat image){
int threshold = 0;
Mat gray( Size( image.cols, image.rows), CV_8UC1, Scalar( 0 ) );
double convert[3] = {0.114478, 0.586611, 0.298912};
//グレースケール化
int channel = image.channels();
for( int y = 0; y < image.rows; y++ ){
for( int x = 0; x < image.cols; x++ ){
for( int c = 0; c < channel; c++ ){
gray.data[ gray.step * y + x ] += static_cast<unsigned char>(image.data[ image.step * y + channel * x ] * convert[ c ]);
}
}
}
imshow( "Viewer", gray );
waitKey( );
destroyWindow("Viewer");
long double max = 0;
for( int i = 0; i < 256; i++){
int m1 = 0;
int m2 = 0;
long int sum1 = 0;
long int sum2 = 0;
int pix1 = 0;
int pix2 = 0;
for( int y = 0; y < gray.rows; y++){
for( int x = 0; x < gray.cols; x++){
if(gray.data[ gray.step * y + x ] <= i){
sum1 += gray.data[ gray.step * y + x ];
pix1 += 1;
}else{
sum2 += gray.data[ gray.step * y + x ];
pix2 += 1;
}
}
}
if(pix1 != 0 && pix2 != 0){
m1 = sum1 / pix1;
m2 = sum2 / pix2;
long double t = ((pix1 * pix2) / ((pix1 + pix2) * (pix1 + pix2))) * (m1 - m2) * (m1 - m2);
if(max < t){
max = t;
threshold = i;
}
}
}
return threshold;
}
//二値化
void dam::binarize(Mat image, int threshold){
Mat gray( Size( image.cols, image.rows), CV_8UC1, Scalar( 0 ) );
double convert[3] = { 0.114478, 0.586611, 0.298912};
int channel = image.channels();
for( int y = 0; y < image.rows; y++ ){
for( int x = 0; x < image.cols; x++ ){
for( int c = 0; c < channel; c++ ){
gray.data[ gray.step * y + x ] += static_cast<unsigned char>(image.data[ image.step * y + channel * x ] * convert[ c ]);
}
}
}
for( int y = 0; y < gray.rows; y++){
for( int x = 0; x < gray.cols; x++){
int point = gray.step * y + x;
if(gray.data[ point ] < threshold){
gray.data[ point ] = 0;
}else{
gray.data[ point ] = 255;
}
}
}
//ウィンドウ表示
imshow( "Viewer", gray );
waitKey( );
destroyWindow("Viewer");
}
//濃度パターン法によるハーフトーニング
void dam::dpm(Mat image){
//グレースケール作成
Mat gray( Size( image.cols, image.rows), CV_8UC1, Scalar( 0 ) );
//濃度パターン解析したものを格納する配列
Mat dpm( Size( image.cols * 4, image.rows * 4), CV_8UC1, Scalar( 0 ) );
double convert[3] = { 0.114478, 0.586611, 0.298912};
int channel = image.channels();
for( int y = 0; y < image.rows; y++ ){
for( int x = 0; x < image.cols; x++ ){
for( int c = 0; c < channel; c++ ){
gray.data[ gray.step * y + x ] += static_cast<unsigned char>(image.data[ image.step * y + channel * x ] * convert[ c ]);
}
}
}
//以下ハーフトーン処理部分
//パターン
unsigned char pat[][16] = {{ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 255, 0,
0, 0, 0, 0},
{ 0, 0, 255, 0,
0, 0, 0, 0,
0, 0, 255, 0,
0, 0, 0, 0},
{ 0, 0, 255, 0,
0, 0, 0, 0,
255, 0, 255, 0,
0, 0, 0, 0},
{ 0, 0, 255, 0,
0, 0, 0, 0,
255, 0, 255, 0,
0, 0, 0, 0},
{ 0, 0, 255, 0,
0, 255, 0, 0,
255, 0, 255, 0,
0, 0, 0, 0},
{ 0, 0, 255, 0,
0, 255, 0, 0,
255, 0, 255, 0,
0, 0, 0, 255},
{ 0, 0, 255, 0,
0, 255, 0, 255,
255, 0, 255, 0,
0, 0, 0, 255},
{ 0, 0, 255, 0,
0, 255, 0, 255,
255, 0, 255, 0,
0, 255, 0, 255},
{ 0, 255, 255, 0,
0, 255, 0, 255,
255, 0, 255, 0,
0, 255, 0, 255},
{ 0, 255, 255, 0,
0, 255, 0, 255,
255, 0, 255, 255,
0, 255, 0, 255},
{ 0, 255, 255, 255,
0, 255, 0, 255,
255, 0, 255, 255,
0, 255, 0, 255},
{ 0, 255, 255, 255,
0, 255, 0, 255,
255, 255, 255, 255,
0, 255, 0, 255},
{ 0, 255, 255, 255,
255, 255, 0, 255,
255, 255, 255, 255,
0, 255, 0, 255},
{ 0, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255,
0, 255, 0, 255},
{ 0, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255,
0, 255, 255, 255},
{ 0, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255},
{ 255, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255}
};
for(int y = 0; y < gray.rows; y++){
for(int x = 0; x < gray.cols; x++){
for(int i = 0; i < 4; i++){
dpm.data[y * 4 * dpm.step + x * 4 + i] = pat[ gray.data[gray.step * y + x] / 16 ][i];
dpm.data[(y * 4 + 1) * dpm.step + x * 4 + i] = pat[ gray.data[gray.step * y + x] / 16 ][i + 4];
dpm.data[(y * 4 + 2) * dpm.step + x * 4 + i] = pat[ gray.data[gray.step * y + x] / 16 ][i + 8];
dpm.data[(y * 4 + 3) * dpm.step + x * 4 + i] = pat[ gray.data[gray.step * y + x] / 16 ][i + 12];
}
}
}
imshow( "Viewer", dpm );
waitKey( );
destroyWindow("Viewer");
}
//ディザ法によるハーフトーニング
void dam::dither(Mat image){
//グレースケール作成
Mat gray( Size( image.cols, image.rows), CV_8UC1, Scalar( 0 ) );
double convert[3] = { 0.114478, 0.586611, 0.298912};
int channel = image.channels();
for( int y = 0; y < image.rows; y++ ){
for( int x = 0; x < image.cols; x++ ){
for( int c = 0; c < channel; c++ ){
gray.data[ gray.step * y + x ] += static_cast<unsigned char>(image.data[ image.step * y + channel * x ] * convert[ c ]);
}
}
}
//以下ハーフトーン処理部分
//ベイヤーパターン
unsigned char bayer[] = { 0, 128, 32, 160,
192, 64, 224, 96,
48, 176, 16, 144,
240, 112, 208, 80};
for(int y = 0; y < gray.rows; y++){
for(int x = 0; x < gray.cols; x++){
if((bayer[(y % 4) * 4 + (x % 4)]) <= gray.data[y * gray.step + x]){
gray.data[y * gray.step + x] = 255;
}else{
gray.data[y * gray.step + x] = 0;
}
}
}
imshow( "Viewer", gray );
waitKey( );
destroyWindow("Viewer");
}
//誤差拡散法によるハーフトーニング
void dam::r_dither(Mat image){
//グレースケール作成
Mat gray( Size( image.cols, image.rows), CV_8UC1, Scalar( 0 ) );
double convert[3] = { 0.114478, 0.586611, 0.298912};
int channel = image.channels();
for( int y = 0; y < image.rows; y++ ){
for( int x = 0; x < image.cols; x++ ){
for( int c = 0; c < channel; c++ ){
gray.data[ gray.step * y + x ] += static_cast<unsigned char>(image.data[ image.step * y + channel * x ] * convert[ c ]);
}
}
}
//以下ハーフトーン処理部分
int e;
for(int y = 0; y < gray.rows; y++){
for(int x = 0; x < gray.cols; x++){
int f = gray.data[y * gray.step + x];
if(f > 127){
gray.data[y * gray.step + x] = 255;
e = f - 255;
}else{
gray.data[y * gray.step + x] = 0;
e = f;
}
if(y != gray.rows && x != gray.cols){
gray.data[y * gray.step + x + 1] += e * (5 / 16);
gray.data[(y + 1) * gray.step + x - 1] += e * (3 / 16);
gray.data[(y + 1) * gray.step + x] += e * (5 / 16);
gray.data[(y + 1) * gray.step + x + 1] += e * (3 / 16);
}
else if(y != gray.rows && x == gray.cols){
gray.data[(y + 1) * gray.step + x - 1] += e * (3 / 16);
gray.data[(y + 1) * gray.step + x] += e * (5 / 16);
}
else if(y == gray.rows && x != gray.cols){
gray.data[y * gray.step + x + 1] += e * (5 / 16);
}
}
}
Mat result( Size( image.cols, image.rows ), CV_8UC3, Scalar( 0 ) );
imshow( "Viewer", gray );
waitKey( );
destroyWindow("Viewer");
}
|