質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

8309閲覧

C++で畳み込み画像処理を実装したい

fu-semo

総合スコア7

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/12/14 03:07

編集2017/12/14 03:24

###C++で畳み込みを実装したい
C++でopencvを用いて畳み込みを実装しています
filter2Dなどの関数がある事は知っていますが、自分で関数を作ります。
自分で実装したコードはエラーは出ませんが出力が元の画像とはかけ離れたものになってしまいます

###原画像、出力画像

原画像
イメージ説明

出力画像
イメージ説明

###該当のソースコード

C++

1void convolution(Mat& src, Mat& mask){ 2 // src:原画像 mask:畳み込むフィルター 3 int srcW = src.rows; 4 int srcH = src.cols; 5 int maskW = mask.rows; 6 int maskH = mask.cols; 7 8 // フィルターの半径 9 int rx=(maskW-1)/2; 10 int ry=(maskH-1)/2; 11 12 // 出力画像を初期化 13 dst=Mat::zeros(srcW, srcH, CV_8U); 14 15 for(int x=0; x<srcW; x++){ 16 for(int y=0; y<srcH; y++){ 17 double sum=0; 18 19 for(int i=0; i<maskW; i++){ 20 int pointx = x-rx+i; 21 for(int j=0; j<maskH; j++){ 22 int pointy = y-ry+j; 23 // pointが原画像の中である(原画像の外を参照する場合は何もしない) 24 if((pointx>=0 && pointx<srcW) && (pointy>=0 && pointy<srcH)){ 25 // フィルターと原画像の積を総和する 26 sum+=kernel.at<unsigned char>(i,j)*src.at<unsigned char>(pointx,pointy); 27 } 28 } 29 } 30 // 結果を出力画像に入れる 31 dst.at<unsigned char>(x,y)=sum; 32 } 33 } 34/* 画素値を0−255にスケーリングする事を試みましたが、結果が変わりませんでした 35 float fmin=FLT_MAX; 36 float fmax=-(FLT_MAX); 37 for(int k=0; k<dst.rows; k++){ 38 for(int l=0; l<dst.cols; l++){ 39 float pixel=dst.at<unsigned char>(k,l); 40 if (pixel > fmax) 41 fmax=pixel; 42 if (pixel < fmin) 43 fmin=pixel; 44 } 45 } 46 47 for(int m=0; m<dst.rows; m++){ 48 for(int n=0; n<dst.cols; n++){ 49 dst.at<unsigned char>(m,n)=(dst.at<unsigned char>(m,n)-fmin)*255.0/(fmax-fmin); 50 } 51 } 52 */ 53}

###試したこと
原画像の外のピクセルを参照していることへの対処やスケーリングなどを加えてみましたが、出力画像はめちゃくちゃのままでした

###補足情報(言語/FW/ツール等のバージョンなど)
コンパイルにはMakefileを使用しています
ソースコードはこちら(問題のファイル名はkadaiC.cpp)

# Makefile template for building OpenCV programs in C # Usage: Change the TARGET to foo when compiling foo.c or foo.cpp # Target program TARGET=kadaiC # Compiler #CC=gcc CC=g++ # Compiler options CFLAGS=`pkg-config --cflags opencv` -O3 LDFLAGS=`pkg-config --libs opencv` OBJS= $(TARGET).o #OBJS= $(TARGET).o src1.o src2.o # Default target all: $(TARGET) # Linking objects $(TARGET): $(OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJS) # Compile C source to objects .c.o: $(CC) $(CFLAGS) -c $< # Compile C++ source to objects .cpp.o: $(CC) $(CFLAGS) -c $< # Clean up for re-building clean: rm *.o

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

OpenCVに関しては全然わからないけど、わからないなりに気になった点を書いておきます。
・kernelとは何なのか。maskと書くべき所がkernelになってるのか、それともmaskとkernelには何か関係があるのか
・unsigned charにしているので、フィルターにマイナスの値が使えない。それで良いのか
・(既に指摘されてますが)sumの値はunsigned charの範囲外かもしれない。dstに入れる直前で if (sum < 0) sum = 0; else if (sum > 255) sum = 255; とでもやっておけば、その場しのぎかもしれないけど少しは改善されるかもしれない
・フィルターに変な値は入ってないか

投稿2017/12/14 12:31

okrt

総合スコア366

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fu-semo

2017/12/18 18:27

回答ありがとうございます maskとkernelは同じ意味で書いてますが、自分でもややこしい変数名で反省しております。お恥ずかしい限りです。 フィルターにマイナスの値は今回は使わないので度外視していましたが、一般的ではありませんでした。ご忠告ありがとうございます。 ご指摘の通り、sumの値がunsigned charの範囲を超えているのが原因でした。現状はうまくいきましたので報告します。
guest

0

ベストアンサー

sumが大きすぎてunsigned charに収まらないのではないでしょうか?
dst.at<unsigned char>(x,y)=sum;dst.at<unsigned char>(x,y) = sum / (maskW * maskH * 255);のようにもっと小さくしてやると変化はありますでしょうか。

投稿2017/12/14 09:13

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fu-semo

2017/12/18 18:24

回答ありがとうございます ご指摘の通りunsigned charの取り得る値の範囲を超えているのが原因でした。現状うまくいきましたので報告します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問