#3
by みえ » 8年前
ところで、グレースケール化や 2 値化といった処理をループで書き下しているのはなぜですか?
それぞれ cvCvtColor と cvThreshold で実現可能なので、もし使えるのであれば OpenCV の API に頼った方が楽だし安全だと思います。
使える API を使用し、また、不要な変数などを取り除いたコードはこちらです。ご参考までに。
コード:
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/highgui/highgui_c.h>
void thinningIte(IplImage *Img_nichi, int pattern){
IplImage *Img_sai = cvCreateImage(cvGetSize(Img_nichi), IPL_DEPTH_8U, 1);
CvScalar ones = {1};
cvSet(Img_sai, ones, NULL);
for (int y = 1; y<Img_nichi->height - 1; y++){
for (int x = 1; x<Img_nichi->width - 1; x++){
int v9, v2, v3;
int v8, v1, v4;
int v7, v6, v5;
v1 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 0, x + 0);
v2 = CV_IMAGE_ELEM(Img_nichi, uchar, y - 1, x + 0);
v3 = CV_IMAGE_ELEM(Img_nichi, uchar, y - 1, x + 1);
v4 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 0, x + 1);
v5 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 1, x + 1);
v6 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 1, x + 0);
v7 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 1, x - 1);
v8 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 0, x - 1);
v9 = CV_IMAGE_ELEM(Img_nichi, uchar, y - 1, x - 1);
int S = (v2 == 0 && v3 == 1) + (v3 == 0 && v4 == 1) +
(v4 == 0 && v5 == 1) + (v5 == 0 && v6 == 1) +
(v6 == 0 && v7 == 1) + (v7 == 0 && v8 == 1) +
(v8 == 0 && v9 == 1) + (v9 == 0 && v2 == 1);
int N = v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9;
int m1 = 0, m2 = 0;
if (pattern == 0) m1 = (v2 * v4 * v6);
if (pattern == 1) m1 = (v2 * v4 * v8);
if (pattern == 0) m2 = (v4 * v6 * v8);
if (pattern == 1) m2 = (v2 * v6 * v8);
if (S == 1 && (N >= 2 && N <= 6) && m1 == 0 && m2 == 0)
CV_IMAGE_ELEM(Img_sai, uchar, y, x) = 0;
}
}
cvAnd(Img_nichi, Img_sai, Img_nichi, NULL);
cvReleaseImage(&Img_sai);
}
IplImage *thinning(IplImage *Img_1){
IplImage *white = cvCreateImage(cvGetSize(Img_1), IPL_DEPTH_8U,1);
CvScalar full_bits = {0xff};
cvSet(white, full_bits, NULL);
IplImage *Img_2 = cvCloneImage(Img_1);
cvDiv(Img_2, white, Img_2, 1);
IplImage *prev = cvCreateImage(cvGetSize(Img_2), IPL_DEPTH_8U, 1);
IplImage *diff = cvCreateImage(cvGetSize(Img_2), IPL_DEPTH_8U, 1);
do {
thinningIte(Img_2, 0);
thinningIte(Img_2, 1);
cvAbsDiff(Img_2, prev, diff);
cvCopy(Img_2, prev, NULL);
} while (cvCountNonZero(diff) > 0);
cvMul(Img_2, white, Img_2, 1);
cvReleaseImage(&white);
cvReleaseImage(&diff);
cvReleaseImage(&prev);
return Img_2;
}
int main(int argc, char* argv[]){
if (argc < 2) return 1;
IplImage *Img_orig; //元画像
IplImage *Img_gray; //グレースケール
IplImage *Img_nichi; //2値
IplImage *Img_sai;
int W, H; //widthとheight
//画像の読み込み
Img_orig = cvLoadImage(argv[1], 1);
W = Img_orig->width;//幅
H = Img_orig->height;//高さ
//画像リソースの確保
Img_gray = cvCreateImage(cvSize(W, H), IPL_DEPTH_8U, 1); //白黒
Img_nichi = cvCreateImage(cvSize(W, H), IPL_DEPTH_8U, 1); //白黒
//グレースケール化
cvCvtColor(Img_orig, Img_gray, CV_BGR2GRAY);
//2値化
cvThreshold(Img_gray, Img_nichi, 10, 255, CV_THRESH_BINARY);
//細線化
Img_sai = thinning(Img_nichi);
//画像の表示
cvShowImage("元画像", Img_orig);
cvShowImage("グレースケール", Img_gray);
cvShowImage("2値 (細線化前)", Img_nichi);
cvShowImage("2値 (細線化後)", Img_sai);
//画像の保存
cvSaveImage("No_5a.bmp", Img_gray, 0);
cvSaveImage("No_5b.bmp", Img_nichi, 0);
cvSaveImage("No_5c.bmp", Img_sai, 0);
//キー入力待機
cvWaitKey(0);
//ウィンドウの破棄
cvDestroyAllWindows();
//画像リソースの解放
cvReleaseImage(&Img_orig);
cvReleaseImage(&Img_gray);
cvReleaseImage(&Img_nichi);
cvReleaseImage(&Img_sai);
return 0;
}
ところで、グレースケール化や 2 値化といった処理をループで書き下しているのはなぜですか?
それぞれ cvCvtColor と cvThreshold で実現可能なので、もし使えるのであれば OpenCV の API に頼った方が楽だし安全だと思います。
使える API を使用し、また、不要な変数などを取り除いたコードはこちらです。ご参考までに。
[code=c]#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/highgui/highgui_c.h>
void thinningIte(IplImage *Img_nichi, int pattern){
IplImage *Img_sai = cvCreateImage(cvGetSize(Img_nichi), IPL_DEPTH_8U, 1);
CvScalar ones = {1};
cvSet(Img_sai, ones, NULL);
for (int y = 1; y<Img_nichi->height - 1; y++){
for (int x = 1; x<Img_nichi->width - 1; x++){
int v9, v2, v3;
int v8, v1, v4;
int v7, v6, v5;
v1 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 0, x + 0);
v2 = CV_IMAGE_ELEM(Img_nichi, uchar, y - 1, x + 0);
v3 = CV_IMAGE_ELEM(Img_nichi, uchar, y - 1, x + 1);
v4 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 0, x + 1);
v5 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 1, x + 1);
v6 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 1, x + 0);
v7 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 1, x - 1);
v8 = CV_IMAGE_ELEM(Img_nichi, uchar, y + 0, x - 1);
v9 = CV_IMAGE_ELEM(Img_nichi, uchar, y - 1, x - 1);
int S = (v2 == 0 && v3 == 1) + (v3 == 0 && v4 == 1) +
(v4 == 0 && v5 == 1) + (v5 == 0 && v6 == 1) +
(v6 == 0 && v7 == 1) + (v7 == 0 && v8 == 1) +
(v8 == 0 && v9 == 1) + (v9 == 0 && v2 == 1);
int N = v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9;
int m1 = 0, m2 = 0;
if (pattern == 0) m1 = (v2 * v4 * v6);
if (pattern == 1) m1 = (v2 * v4 * v8);
if (pattern == 0) m2 = (v4 * v6 * v8);
if (pattern == 1) m2 = (v2 * v6 * v8);
if (S == 1 && (N >= 2 && N <= 6) && m1 == 0 && m2 == 0)
CV_IMAGE_ELEM(Img_sai, uchar, y, x) = 0;
}
}
cvAnd(Img_nichi, Img_sai, Img_nichi, NULL);
cvReleaseImage(&Img_sai);
}
IplImage *thinning(IplImage *Img_1){
IplImage *white = cvCreateImage(cvGetSize(Img_1), IPL_DEPTH_8U,1);
CvScalar full_bits = {0xff};
cvSet(white, full_bits, NULL);
IplImage *Img_2 = cvCloneImage(Img_1);
cvDiv(Img_2, white, Img_2, 1);
IplImage *prev = cvCreateImage(cvGetSize(Img_2), IPL_DEPTH_8U, 1);
IplImage *diff = cvCreateImage(cvGetSize(Img_2), IPL_DEPTH_8U, 1);
do {
thinningIte(Img_2, 0);
thinningIte(Img_2, 1);
cvAbsDiff(Img_2, prev, diff);
cvCopy(Img_2, prev, NULL);
} while (cvCountNonZero(diff) > 0);
cvMul(Img_2, white, Img_2, 1);
cvReleaseImage(&white);
cvReleaseImage(&diff);
cvReleaseImage(&prev);
return Img_2;
}
int main(int argc, char* argv[]){
if (argc < 2) return 1;
IplImage *Img_orig; //元画像
IplImage *Img_gray; //グレースケール
IplImage *Img_nichi; //2値
IplImage *Img_sai;
int W, H; //widthとheight
//画像の読み込み
Img_orig = cvLoadImage(argv[1], 1);
W = Img_orig->width;//幅
H = Img_orig->height;//高さ
//画像リソースの確保
Img_gray = cvCreateImage(cvSize(W, H), IPL_DEPTH_8U, 1); //白黒
Img_nichi = cvCreateImage(cvSize(W, H), IPL_DEPTH_8U, 1); //白黒
//グレースケール化
cvCvtColor(Img_orig, Img_gray, CV_BGR2GRAY);
//2値化
cvThreshold(Img_gray, Img_nichi, 10, 255, CV_THRESH_BINARY);
//細線化
Img_sai = thinning(Img_nichi);
//画像の表示
cvShowImage("元画像", Img_orig);
cvShowImage("グレースケール", Img_gray);
cvShowImage("2値 (細線化前)", Img_nichi);
cvShowImage("2値 (細線化後)", Img_sai);
//画像の保存
cvSaveImage("No_5a.bmp", Img_gray, 0);
cvSaveImage("No_5b.bmp", Img_nichi, 0);
cvSaveImage("No_5c.bmp", Img_sai, 0);
//キー入力待機
cvWaitKey(0);
//ウィンドウの破棄
cvDestroyAllWindows();
//画像リソースの解放
cvReleaseImage(&Img_orig);
cvReleaseImage(&Img_gray);
cvReleaseImage(&Img_nichi);
cvReleaseImage(&Img_sai);
return 0;
}[/code]