前提・実現したいこと
Java版OpenCV3.4.2で二値画像にラベリングをし、連結成分の面積が一番大きな部分以外を黒で塗りつぶしたいです(切り抜き)。
connectedComponentsWithStatsを用いて面積情報を取得するところまではできたのですが
指定したラベルの連結成分の色を変えることができずに困っています。
該当のソースコード
Java
public void getframe(Mat src_img, Mat dst_img){ int rows = src_img.width(); int cols = src_img.height(); //二値化 Mat gray_img = new Mat(cols,rows, CvType.CV_8UC1); Imgproc.cvtColor(src_img,gray_img,Imgproc.COLOR_RGB2GRAY); int blockSize=Math.min(cols,rows)/40*2+1; Imgproc.adaptiveThreshold(gray_img,dst_img,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY_INV,blockSize,3); //ラベリング実行 Mat labelImage = new Mat(cols,rows,CvType.CV_32S); Mat stats = new Mat(); Mat centroids = new Mat(); int nLabels = Imgproc.connectedComponentsWithStats(dst_img,labelImage,stats,centroids,8,CvType.CV_32S); //面積情報を取得 int[] result = new int[nLabels]; int max = 0; int count = 0; for(int i=1;i<nLabels;i++){ stats.get(i,Imgproc.CC_STAT_AREA,result); if(max < result[i]){ max = result[i]; count = i; } } //連結成分の中で一番面積が大きいもの以外を黒塗り for(int i=1;i<nLabels;i++){ if(i != count){ //黒で塗りつぶす } } }
試したこと
c++でのconnectedComponentsにおける指定したラベルの塗りつぶしを参考にしています。
しかし、Java版OpenCVに画素値を変更するVec3bが無いようで、
代わりに指定した座標の画素値を取り出す「mat.get()」と
指定した座標の画素値を変更する「mat.put()」を利用しようと試みたのですがどうにもうまくいきません。
そもそも参考にしているサイトにおいて
std::vector<cv::Vec3b> colors(nLabels);
というVec3b型の可変長配列を作っているところまでは理解できるのですが
colors[0] = cv::Vec3b(0, 0, 0);
上記のようにcolols[ラベルの番号]だけで指定したラベルにアクセスできているというのが理解できません。
colorsはあくまでnLabels個のVec3b型の配列として定義されただけなのに
なぜラベル番号を引数に入れるだけで該当ラベルの画素値を操作できるようになるのでしょうか。
伝わりづらいしし質問で申し訳ありませんがご教授いただけると幸いです。
c++
std::vector<cv::Vec3b> colors(nLabels); colors[0] = cv::Vec3b(0, 0, 0); for(int label = 1; label < nLabels; ++label) { colors[label] = cv::Vec3b((rand()&255), (rand()&255), (rand()&255)); } // ラベリング結果の描画 cv::Mat dst(src.size(), CV_8UC3); for(int y = 0; y < dst.rows; ++y) { for(int x = 0; x < dst.cols; ++x) { int label = labelImage.at<int>(y, x); cv::Vec3b &pixel = dst.at<cv::Vec3b>(y, x); pixel = colors[label]; }
まだ回答がついていません
会員登録して回答してみよう