OpenCVを使って輪郭を表示してみる
前回と前々回につかった白い部分を拡大する方法と黒い部分を拡大する方法を組み合わせて
Lenaさんの輪郭を浮かびあがせる。白色拡大のLenaさんから黒色拡大のLenaさんを引いてみる
と、あら不思議輪郭が出てきた。つまり輝度の変換の大きいところが白くなっている。
//画面をだすよ void display(cv::Mat image) { //前の記事を参考 } //受け取ったピクセル位置の八方のなかで一番数値が小さいピクセルの数字を求める //Dilation 3x3 uchar getMin(cv::Mat image, int y, int x) { //前の記事を参考 } //受け取ったピクセル位置の八方のなかで一番数値が大きいピクセルの数字を求める //Erosion 3x3 uchar getMax(cv::Mat image, int y, int x) { //前の記事を参考 } // // ここから // int main(int argc, char** argv) { //lenaさん登場!! cv::Mat lena = cv::imread("lena.jpg"); //lenaさん白黒レトロ cv::cvtColor(lena, lena, CV_RGB2GRAY); //lenaさんと同じサイズの画像 int cols = lena.cols; int rows = lena.rows; cv::Mat tmp = cv::Mat::zeros(cols, rows, CV_8UC1); cv::Mat tmp2 = cv::Mat::zeros(cols, rows, CV_8UC1); cv::Mat image = cv::Mat::zeros(cols, rows, CV_8UC1); cv::Mat image2 = cv::Mat::zeros(cols, rows, CV_8UC1); cv::Mat image3 = cv::Mat::zeros(cols, rows, CV_8UC1); image = lena.clone(); image2 = lena.clone(); uchar change; uchar change2; for (int t = 0; t < 1; t++) { for (int j = 2; j < rows - 2; j++) { for (int i = 2; i < cols - 2; i++) { change = getMax(image,j,i); change2 = getMin(image2,j,i); tmp.at<uchar>(j, i) = cv::saturate_cast<uchar>(change); tmp2.at<uchar>(j, i) = cv::saturate_cast<uchar>(change2); } } image = tmp.clone(); image2 = tmp2.clone(); } for (int j = 2; j < rows - 2; j++) { for (int i = 2; i < cols - 2; i++) { //明るい画像から暗い画像を引く change = image.at<uchar>(j, i) - image2.at<uchar>(j, i); tmp.at<uchar>(j, i) = cv::saturate_cast<uchar>(change); } } image3 = tmp.clone(); //画面に出して!! display(image3); }
輪郭Lenaさん
OpenCVを使ってLenaさんの白いところを拡大する。
こんどは黒いところでなくて白いところを拡大してみる。 これが何の役に立つのか?
//画面をだすよ void display(cv::Mat image) { //まえの記事をみてね } //受け取ったピクセル位置の八方のなかで一番数値が大きいピクセルの数字を求める uchar getMax(cv::Mat image, int y, int x) { uchar curr = 0; uchar max = 0; for (int j = -1; j <= 1; j++) { for (int i = -1; i <= 1; i++) { curr = image.at<uchar>(y + j , x + i); if (curr > max){ max = curr; } } } return max; } // // ここから // int main(int argc, char** argv) { //lenaさん登場!! cv::Mat lena = cv::imread("lena.jpg"); //lenaさん白黒レトロ cv::cvtColor(lena, lena, CV_RGB2GRAY); int cols = lena.cols; int rows = lena.rows; //lenaさんと同じサイズの画像 cv::Mat tmp = cv::Mat::zeros(cols, rows, CV_8UC1); cv::Mat image = cv::Mat::zeros(cols, rows, CV_8UC1); image = lena.clone(); uchar change; //2回も拡大するね。 for (int t = 0; t < 2; t++) { for (int j = 2; j < rows - 2; j++) { for (int i = 2; i < cols - 2; i++) { change = getMax(image,j,i); tmp.at<uchar>(j, i) = cv::saturate_cast<uchar>(change); } } image = tmp.clone(); } //画面に出して!! display(image); }
白いところが太くなったLenaさん。エッジは??
OpenCVを使ってLenaさんの黒いところを拡大する。(0009)
Lenaさんの黒いところをちょっと拡大する。 これが何の役に立つのか?
//画面をだすよ void display(cv::Mat image) { //まえの記事をみてね。 } //受け取ったピクセル位置の八方のなかで一番数値が小さいピクセルの数字を求める uchar getMin(cv::Mat image, int y, int x) { uchar curr = image.at<uchar>(y , x); uchar min = 255; for (int j = -1; j <= 1; j++) { for (int i = -1; i <= 1; i++) { curr = image.at<uchar>(y + j , x + i); if (curr < min){ min = curr; } } } return min; } // // ここから // int main(int argc, char** argv) { //lenaさん登場!! cv::Mat lena = cv::imread("lena.jpg"); //lenaさん白黒レトロ cv::cvtColor(lena, lena, CV_RGB2GRAY); int cols = lena.cols; int rows = lena.rows; //lenaさんと同じサイズの画像 cv::Mat tmp = cv::Mat::zeros(cols, rows, CV_8UC1); cv::Mat image = cv::Mat::zeros(cols, rows, CV_8UC1); image = lena.clone(); uchar change; //2回も拡大するね。 for (int t = 0; t < 2; t++) { for (int j = 2; j < rows - 2; j++) { for (int i = 2; i < cols - 2; i++) { change = getMin(image,j,i); tmp.at<uchar>(j, i) = cv::saturate_cast<uchar>(change); } } image = tmp.clone(); } //画面に出して!! display(image); }
黒いところが太くなった!! 回りのピクセルは黒(ごかんべんを!!)
OpenCVを使ってLenaさんをぼかす2にする。(0008)
Lenaさんぼかしの2回めです。 えせガウスぼかし??
//画面をだすよ void display(cv::Mat image) { //以前の記事をみてね!! } int main(int argc, char** argv) { //lenaさん登場!! cv::Mat lena = cv::imread("lena.jpg"); //lenaさん白黒レトロ cv::cvtColor(lena, lena, CV_RGB2GRAY); int cols = lena.cols; int rows = lena.rows; //lenaさんと同じサイズの画像 cv::Mat image = cv::Mat::zeros(cols, rows, CV_8UC1); uchar up,down,left,right; uchar upleft,downleft; uchar upright,downright; uchar anchor; for (int j = 1; j < rows - 1; j++) { for (int i = 1; i < cols - 1; i++) { up = lena.at<uchar>(j - 1, i); down = lena.at<uchar>(j + 1, i); left = lena.at<uchar>(j, i - 1); right = lena.at<uchar>(j, i + 1); upleft = lena.at<uchar>(j - 1, i-1); upright = lena.at<uchar>(j - 1, i+1); downleft = lena.at<uchar>(j + 1, i-1); downright = lena.at<uchar>(j + 1, i+1); anchor = lena.at<uchar>(j, i); image.at<uchar>(j, i) = cv::saturate_cast<uchar>( anchor*4/16 +up*2/16 +down*2/16 +left*2/16 +right*2/16 +upleft*1/16 +upright*1/16 +downleft*1/16 +downright*1/16 ); } } //画面に出して!! display(image); }
オリジナル
ぼかし2 (あんまり変わらん!! 目の回りはエッジがシャープ)
参考ぼかし1
OpenCVを使ってLenaさんをぼかす。(0007)
OpenCVを使ってLenaさんをぼかす。 エッジはごかんべんを!!
//画面をだすよ void display(cv::Mat image) { //名前をつける std::string windowName = "windowName"; cv::namedWindow(windowName); //画面位置固定 cv::moveWindow(windowName, 100, 100); //画面出た!! cv::imshow(windowName, image); //なにかキーをおして~ cv::waitKey(0); //整理整頓 cv::destroyWindow(windowName); } // // ここから // int main(int argc, char** argv) { //lenaさん登場!! cv::Mat lena = cv::imread("lena.jpg"); //lenaさん白黒レトロ cv::cvtColor(lena, lena, CV_RGB2GRAY); int cols = lena.cols; int rows = lena.rows; //lenaさんと同じサイズの画像 cv::Mat image = cv::Mat::zeros(cols, rows, CV_8UC1); uchar up,down,left,right; uchar upleft,downleft; uchar upright,downright; uchar anchor; for (int j = 1; j < rows - 1; j++) { for (int i = 1; i < cols - 1; i++) { up = lena.at<uchar>(j - 1, i); down = lena.at<uchar>(j + 1, i); left = lena.at<uchar>(j, i - 1); right = lena.at<uchar>(j, i + 1); upleft = lena.at<uchar>(j - 1, i-1); upright = lena.at<uchar>(j - 1, i+1); downleft = lena.at<uchar>(j + 1, i-1); downright = lena.at<uchar>(j + 1, i+1); anchor = lena.at<uchar>(j, i); image.at<uchar>(j, i) = cv::saturate_cast<uchar>( anchor/9 +up/9 +down/9 +left/9 +right/9 +upleft/9 +upright/9 +downleft/9 +downright/9 ); } } //画面に出して!! display(image); }
白黒
ぼかし
OpenCVを使ってLenaさんをシャープにする。(0006)
Lenaさんをシャープにするには隣のピクセルの値を使う
まず描くピクセル値を5倍、それだと濃すぎるので上、下、右、左の
ピクセル値を5倍した値から引く、0-255の範囲を越えると強制的に0か255にする。
隣とくらべて明るいところはさらに明るく!! その反対は暗く!!
Lenaさん回りの1ピクセルは真っ黒です。
//画面をだすよ void display(cv::Mat image) { //名前をつける std::string windowName = "windowName"; cv::namedWindow(windowName); //画面位置固定 cv::moveWindow(windowName, 100, 100); //画面出た!! cv::imshow(windowName, image); //なにかキーをおして~ cv::waitKey(0); //整理整頓 cv::destroyWindow(windowName); } int main(int argc, char** argv) { //lenaさん登場!! cv::Mat lena = cv::imread("lena.jpg"); int cols = lena.cols; int rows = lena.rows; //lenaさんと同じサイズの画像 cv::Mat image = cv::Mat::zeros(cols, rows, CV_8UC3); uchar ue[3]; uchar shita[3]; uchar hidari[3]; uchar migi[3]; for (int j = 1; j < rows - 1; j++) { for (int i = 1; i < cols - 1; i++) { for (int k = 0; k < 3; k++) { ue[k] = lena.at<cv::Vec3b>(j - 1, i)[k]; shita[k] = lena.at<cv::Vec3b>(j + 1, i)[k]; hidari[k] = lena.at<cv::Vec3b>(j, i - 1)[k]; migi[k] = lena.at<cv::Vec3b>(j, i + 1)[k]; image.at<cv::Vec3b>(j, i)[k] = cv::saturate_cast<uchar>( lena.at<cv::Vec3b>(j, i)[k] * 5 - ue[k] - shita[k] - hidari[k] - migi[k] ); } } } //画面に出して!! display(image); }
オリジナル
シャープLenaさん (ノイズもシャープに!!)
OpenCVを使ってLenaさんを減色にする。(0005)
Lenaさん画像は256x256x256の16777216色だが、減色して64色にしてみる。
256を64で割ると各色4種類。4x4x4=64色、減色にともなって暗くなるので
ちょっと明るくする加工を少し追加。
//画面をだすよ void display(cv::Mat image) { //名前をつける std::string windowName = "windowName"; cv::namedWindow(windowName); //画面位置固定 cv::moveWindow(windowName,100,100); //画面出た!! cv::imshow(windowName, image); //なにかキーをおして~ cv::waitKey(0); //整理整頓 cv::destroyWindow(windowName); } // // ここから // int main(int argc, char** argv) { //lenaさん登場!! cv::Mat lena = cv::imread("lena.jpg"); int cols = lena.cols; int rows = lena.rows; int reduce = 256 / 4; for (int j = 0; j < rows-10; j++) { for (int i = 0; i < cols ; i++) { for (int k = 0; k < 3 ; k++) { image.at<cv::Vec3b>(j, i)[k] = lena.at<cv::Vec3b>(j, i)[k] / reduce * reduce + reduce/2; } } } //画面に出して!! display(image); }
オリジナルLenaさん
減色Lenaさん