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

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

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

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

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

1回答

10312閲覧

openCVを使った画素値取得とその座標の保存方法

shutein

総合スコア14

OpenCV

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

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2017/12/06 06:45

編集2017/12/07 06:58

###前提・実現したいこと
私は今、androidstudioでJavaとopencvを使って
画像認識を利用したアプリを開発しています。

その中でImgproc.GaussianBlur()を使い平滑化したのですが、
平滑化した画像「avem2」に対して一定大きさ以上の画素値(輝度値?)を持つ画素を見つけ
座標(x、y)を保存したいと考えています。

平滑化を行う前は2値化した画像で行っています。

###発生している問題・エラーメッセージ
画像の全画素を探査し一定の値を持つ画素の座標を保存する方法を
教えて欲しいです。

調べても画素の探査のみなら
for (int i=0;i< m_temp.height();i=i++) {
for (int j = 0;j< m_temp.width();j= j++)
のようなforループを使えば出来るとは分かったものの
その後の処理が出来るかまでは判明しませんでした。

(追加2)
私なりにやってみましたが、一定の画素値以上のみを取り出すことができず、
エラーが発生してしまいました。

発生したエラー E/AndroidRuntime: FATAL EXCEPTION: Thread-3 Process: com.example.janome.color2, PID: 6055 java.lang.UnsupportedOperationException: Mat data type is not compatible: 5 at org.opencv.core.Mat.get(Mat.java:1015) at com.example.janome.color2.MainActivity.onCameraFrame(MainActivity.java:229) at org.opencv.android.CameraBridgeViewBase$CvCameraViewListenerAdapter.onCameraFrame(CameraBridgeViewBase.java:163) at org.opencv.android.CameraBridgeViewBase.deliverAndDrawFrame(CameraBridgeViewBase.java:399) at org.opencv.android.JavaCameraView$CameraWorker.run(JavaCameraView.java:352) at java.lang.Thread.run(Thread.java:776)

もしかして
mat.get(y,x)で画素値を取り出すことはできないのでしょうか。

以下コードです。

int r =0; int o=0; // double pix=0; double [] data =new double[avem2.width()*avem2.height()]; double[][] data2 =new double[2][avem2.width()*avem2.height()]; avem2.get(0,0,data); for(int y=0;y<avem2.height();y++) { for (int x = 0; x < avem2.width(); x++) { // avem2.get(y,x); //画素値にアクセス // System.out.println("値は"+data[o]); // pix=data[o]; if(data[o]>0.98){ data2[0][r]=x; data2[1][r]=y; // System.out.println(+(r+1)+"番目の座標が"+data2[0][r]+","+data2[1][r]); System.out.println("x座標は"+data2[0][r]+"y座標は"+data2[1][r]); o++; r++; } } }

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

Java

1 private Mat m_temp; //抽出結果の画像 2 3 public Mat onCameraFrame(Mat inputFrame) { 4 Mat src = inputFrame; 5 Mat dst = Mat.zeros(inputFrame.width(), inputFrame.height(), CV_8U); 6 Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2HSV); 7 8 Mat src2 = dst; 9 Mat dst2 = Mat.zeros(inputFrame.width(), inputFrame.height(), CV_8U); 10 Scalar low = new Scalar(165, 20, 30);//下限  変更前(10,20,30) S,Vはあまり変えない方が良い? 11 Scalar high = new Scalar(179, 255, 255);//上限 変更前(179,255,255) 12 Core.inRange(src2, low, high, dst2); //色抽出 13 14 15 16 //画面をタッチすると表示画面が保持される 17 if (touId ==2) { 18 // return m_temp; // 保持した画像を代わりに表示する。画像は変化しないので、以降の処理は必要ない 19 touId++; 20 int size = (int) m_temp.total() * m_temp.channels(); //「size」はMatの大きさ的なモノ 21 byte[] temp = new byte[size]; //sizeの値を取るのに使うだけ 22 m_temp.get(0, 0, temp); //mat to array 23 // System.out.println(size); =2073600 24 int stride = 10; 25 int n=0; 26 double ave[] = new double[size/stride/stride]; 27 28 for (int i=0;i< m_temp.height();i=i+stride) { 29 for (int j = 0; j < m_temp.width(); j = j + stride) { 30 double sum = 0; 31 for (int k = i; k < i + stride; k++) { 32 for (int l = j; l < j + stride; l++) { 33 sum += temp[k * m_temp.width() + l]; 34 } 35 } 36 37 38 double relt = sum / stride / stride * -1.0; //平均を求める 符号を正に 39 40 41 if (relt >= 0.7) { //閾値の設定(relt3が小さいため0しか出ない) 42 relt = 1.0; 43 } else { 44 relt = 0.0; 45 } 46 ave[n] = relt; 47// System.out.println(+n +"番目は"+"ave="+ave[n]); 48 n++; //n=20736 49 } 50 } 51 // System.out.println("m_temp.width()="+m_temp.width()+"m_temp.height()="+m_temp.height()); width=1920 height=1080 →プーリングで192 , 108 に 52 Mat avem =new Mat(108,192,CV_32F); 53 avem.put(0,0,ave); // 求めた配列をMatに変換した 54 // System.out.println(avem.dump()); 55 56 Mat avem2 =new Mat(108,192,CvType.CV_32F); 57 Imgproc.GaussianBlur(avem,avem2,new Size(31,31),0,0); // 平滑化 58 59 int r =0; 60 int o=0; 61 double [] data =new double[avem2.width()*avem2.height()]; 62 double[][] data2 =new double[2][]; 63 64 for(int y=0;y<avem2.width();y++) { 65 for (int x = 0; x < avem2.height(); x++) { 66 avem2.get(x,y,data); 67 // avem2.get(x,y); //画素値にアクセス 68 System.out.println("値は"+data[o]); 69 o++; 70 if( data[o] >0.98){ 71 data2[0][r]=x; 72 data2[1][r]=y; 73 // System.out.println(+(r+1)+"番目の座標が"+data2[0][r]+","+data2[1][r]); 74 r++; 75 } 76 } 77 } 78 79 // 最大値を見つけられたが、白い部分を見つけるに至っていない。 80 81 82// Core.MinMaxLocResult max =Core.minMaxLoc(avem2); //最大値を求める部分 83// System.out.println("avem2の最大値="+max.maxVal); //avem2の最大値=1.000000238418579 0.9895517826080322 84// System.out.println("点数は"+point); 85 //固まりを見つけて点数を求めるのはここから↓ 86// for(n=0;n<=20628;n=n+108){ 87// for (n = 0; n < 108; n++) { 88// if(ave[n]==1){ 89// for(n=n+1;n%108==107;n++){ 90// if(ave[n]==1){ 91// 92// } 93 94// 107 > 215 > 323 > 431 n%108==107 95// } 96 97// } 98// } 99// } 100// } 101 return m_temp; 102 } 103 104 if(touId>2){ 105 return m_temp; 106 } 107 108 109 //ここに赤(-1)がいくつ連続するか「固まっているか」を探す内容を書く! 110 111 //(例) 10×10 ピクセルごとに走査(縦→横方向)して ピクセル内の総和(0と-1の総和)÷総ピクセル数で一つの値を求める。 112 // そして閾値を決め、さっきの値を含むか否か分ける。(白の割合がどの程度) 閾値以上であればフラグ(引数的な?)を立てる 113 // また、走査時に白と黒の境の座標などを記録?しておく。 114 //境界の中点の座標を今度は横→縦方向で走査しフラグが重なるか調べることで白い塊が見つかるはず・・(多分) 115 116 /*if (color.val[0] == 0) { 117 Scalar targetColor = inputFrame.get(i, j);*/ 118 119 120 121 if (touId == 1) { 122 touId++; 123 m_temp = dst2; //抽出結果を保持する 124 } 125 return dst2; 126 } 127 128 @Override 129 public boolean onTouchEvent (MotionEvent ev) { 130 switch (ev.getAction()) { 131 case ACTION_DOWN: 132 //画面がタッチされたときの動作 133 if (touId == 0) { 134 touId = 1; 135 } 136 break; 137 case MotionEvent.ACTION_CANCEL: 138 //他の要因によってタッチがキャンセルされたときの動作 139 break; 140 } 141 return super.onTouchEvent(ev); 142 }} 143

###補足情報(言語/FW/ツール等のバージョンなど)
androidstudio 2.3.1
java
OpenCV 3.0.0

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

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

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

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

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

guest

回答1

0

Q103546.java

java

1package tsukka.teratail.questions.q103546; 2 3import java.util.HashSet; 4import java.util.Set; 5import org.opencv.core.Core; 6import org.opencv.core.CvType; 7import org.opencv.core.Mat; 8import org.opencv.core.Size; 9import org.opencv.imgcodecs.Imgcodecs; 10import org.opencv.imgproc.Imgproc; 11import tsukka.utility.function.BytePredicate; 12 13/** 14 * 15 * @author tsukka 16 */ 17public class Q103546 { 18 public static void main (String... args){ 19 System.out.println(System.getProperty("java.library.path")); 20 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 21 //画像読み込み 22 Mat im = Imgcodecs.imread("test.png"); // 入力画像の取得 23 24 //二値化 25 Imgproc.cvtColor(im, im, Imgproc.COLOR_BGR2GRAY); //グレースケールに変換 26 Imgproc.threshold(im, im, 0, 255, Imgproc.THRESH_OTSU); //閾値を自動で設定 27 //二値化ここまで 28 29 Mat avem2=new Mat(im.size(),CvType.CV_8U); 30 //平滑化 31 Imgproc.GaussianBlur(im, avem2, new Size(17,13), 0, 0); 32 33 //書き込み 34 //Imgcodecs.imwrite("out.png", avem2); 35 36 //画素値250以上のpointを取得してsetに代入 37 Set<IntPoint> s=getMatchPoints(avem2,c->c>(byte)250);//255*0.98 38 //出力 39 s.forEach(System.out::println); 40 } 41 /** 42 * org.opencv.core.Pointはdoubleしか扱えない罠 43 * @param avem2 グレースケールあるいは二値画像 44 * @param tester 条件 ちなみに画素値が渡されてくる 45 * @return 条件を満たした座標のデータ 46 */ 47 public static Set<IntPoint> getMatchPoints(Mat avem2,BytePredicate tester){ 48 int width=avem2.width(); 49 int height=avem2.height(); 50 byte [] data =new byte[width*height]; 51 avem2.get(0,0,data); 52 HashSet<IntPoint> ret=new HashSet<>(); 53 for(int y=0;y<height;y++) { 54 for (int x = 0; x < width; x++) { 55 if(tester.test(data[y*width+x])){ 56 ret.add(new IntPoint(x,y)); 57 } 58 } 59 } 60 return ret; 61 } 62 63}

IntPoint.java

java

1package tsukka.teratail.questions.q103546; 2 3import org.opencv.core.Point; 4 5/** 6 * 7 * @author tsukka 8 */ 9public class IntPoint { 10 11 public int x, y; 12 13 public IntPoint(int x, int y) { 14 this.x = x; 15 this.y = y; 16 } 17 18 19 @Override 20 public String toString() { 21 return '(' + Integer.toString(x) + ',' + Integer.toString(y) + ')'; 22 } 23 24 public Point toPoint() { 25 return new Point(x, y); 26 } 27} 28

BytePredicate.java

java

1package tsukka.utility.function; 2 3/** 4 * 5 * @author tsukka 6 */ 7@FunctionalInterface 8public interface BytePredicate { 9 default BytePredicate and​(BytePredicate other){ 10 return b->this.test(b)&&other.test(b); 11 } 12 default BytePredicate negate​(){ 13 return b->!this.test(b); 14 } 15 default BytePredicate or​(BytePredicate other) { 16 return b->this.test(b)||other.test(b); 17 } 18 boolean test(byte value); 19}

byteでならとれると思われる
ちなみに白なら-1(255)黒なら0
1ピクセル当たり1インデックス

ラムダとか使えないなら適宜書き換えてください

投稿2017/12/07 07:02

編集2017/12/10 15:06
tignear

総合スコア260

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

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

shutein

2017/12/10 13:33

回答ありがとうございます。 目を通したのですが、 Q103546.javaのmainの部分で何をしているか教えて頂きたいです。
tignear

2017/12/10 15:07 編集

そこは質問者様の質問にあったように画像を読み込みそれに対して二値化した後平滑化を行ない状況を合わせています その後平滑化画像を書き出し(これいらないやつですね) さらにgetMatchPointsメソッドを呼び出して条件に合う点を抽出(今回は画素値250以上を対象にしました) 最後にそれを表示しています 全体の説明はこんなところです 更にわからないところがあればどこがわからないのか詳しくお願いします ちなみにgetMatchPointsメソッドの使い方がこんな感じ程度の意味しかありません 直接の回答はgetMatchPointsメソッドになります
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問