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

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

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

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

Java

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

Android Studio

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

Q&A

解決済

2回答

3856閲覧

[OpenCV for Android]検出した直線全ての上に赤線を表示させたい[HoughLinesP]

mr_shirohige

総合スコア13

OpenCV

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

Java

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

Android Studio

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

0グッド

0クリップ

投稿2019/01/23 05:26

編集2019/01/23 11:47

前提・実現したいこと

Android StudioにてOpenCV for Androidを用い、端末内の画像を読み取り、直線検出を行ったのち、元画像にその直線全ての上に赤線を表示させる動作の実現を目指しています。

発生している問題・エラーメッセージ

五線譜の実線だけが引かれた画像をサンプルとして用いたのですが、直線が一本だけしか検出されず他の直線の上に赤線が引かれていません。
サンプルイメージ説明
エッジ検出までの実行結果イメージ説明
実行結果イメージ説明
初心者なため、おかしなコードの書き方をしているかもしれませんが、何卒訂正、解決策をご教授いただければ幸いです。

エラーメッセージ

該当のソースコード

java

1 2import android.content.Intent; 3import android.graphics.Bitmap; 4import android.graphics.BitmapFactory; 5import android.net.Uri; 6import android.os.Bundle; 7import android.os.ParcelFileDescriptor; 8import android.support.v7.app.AppCompatActivity; 9import android.view.View; 10import android.widget.ImageView; 11 12import org.opencv.android.Utils; 13import org.opencv.core.Mat; 14import org.opencv.core.Point; 15import org.opencv.core.Scalar; 16import org.opencv.imgproc.Imgproc; 17 18import java.io.FileDescriptor; 19import java.io.IOException; 20 21public class MainActivity extends AppCompatActivity { 22 private static final int RESULT_PICK_IMAGEFILE = 1000; 23 private ImageView imageView; 24 Bitmap btmp; 25 Bitmap rtn_btmap; 26 27 static { 28 System.loadLibrary("opencv_java3"); 29 } 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.activity_main); 35 36 imageView = (ImageView) findViewById(R.id.image_view); 37 38 findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() { 39 @Override 40 public void onClick(View v) { 41 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); 42 intent.addCategory(Intent.CATEGORY_OPENABLE); 43 intent.setType("image/*"); 44 startActivityForResult(intent, RESULT_PICK_IMAGEFILE); 45 } 46 }); 47 } 48 49 protected void onRestart() { 50 super.onRestart(); 51 onImageScan(); 52 } 53 54 public void onActivityResult(int requestCode, int resultCode, Intent resultData) { 55 if (requestCode == RESULT_PICK_IMAGEFILE && resultCode == RESULT_OK) { 56 Uri uri = null; 57 if (resultData != null) { 58 uri = resultData.getData(); 59 60 try { 61 Bitmap bmp = getBitmapFromUri(uri); 62 imageView.setImageBitmap(bmp); 63 btmp = Bitmap.createBitmap(bmp); 64 } catch (IOException e) { 65 e.printStackTrace(); 66 } 67 } 68 } 69 } 70 71 public Bitmap getBitmapFromUri(Uri uri) throws IOException { 72 ParcelFileDescriptor parcelFileDiscriptor = getContentResolver().openFileDescriptor(uri, "r"); 73 FileDescriptor fileDescriptor = parcelFileDiscriptor.getFileDescriptor(); 74 Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor); 75 parcelFileDiscriptor.close(); 76 return image; 77 } 78 79 private void onImageScan() { 80 Mat mat = new Mat(); 81 Utils.bitmapToMat(btmp, mat); 82 83 mat = getThreshold(mat); 84 rtn_btmap = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.ARGB_8888); 85 Utils.matToBitmap(mat, rtn_btmap); 86 imageView.setImageBitmap(rtn_btmap); 87 } 88 89 private Mat getThreshold(Mat mat) { 90 Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY); 91 Imgproc.threshold(mat, mat, 225, 255, Imgproc.THRESH_BINARY_INV); 92 Imgproc.Canny(mat,mat,10,225,3,true); 93 Mat linesMat = new Mat(); 94 Imgproc.HoughLinesP(mat, linesMat, 1, Math.PI / 180, 300); 95 Mat bmpmat = new Mat(); 96 Utils.bitmapToMat(btmp, bmpmat); 97 double[] data; 98 Point pt1 = new Point(); 99 Point pt2 = new Point(); 100 for (int i = 0; i < linesMat.cols(); i++){ 101 data = linesMat.get(0, i); 102 pt1.x = data[0]; 103 pt1.y = data[1]; 104 pt2.x = data[2]; 105 pt2.y = data[3]; 106 Imgproc.line(bmpmat, pt1, pt2, new Scalar(255, 0, 0), 1); 107 } 108 return (bmpmat); 109 } 110} 111

試したこと

HoughLinesP()内のthresholdの値等のパラメータ調整を行ってみましたが、赤線が引かれる直線の位置が変化するのみででした。
このサイト様(http://google-os.blog.jp/archives/50716505.html)を参考にしHoughLinesP~Imgproc.lineの処理を置き換えて見たところ下記のエラーが出ました。(4890fcd826a22845b8803bb923300310.jpeg)
Caused by: java.lang.UnsupportedOperationException:Provided data element number (2) should be multiple of the Mat channels count (4)

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

wwbQzhMkhhgEmhU

2019/01/23 10:19

OpenCVは全く使ったことがないので答えもヒントも分かりませんが、画像処理をかけたなら、各処理ごとに出力画像を見ないと分からないと思いますよ。
mr_shirohige

2019/01/23 10:47

グレースケール化、二値化、色調反転、エッジ検出を行ったのち直線検出をかけております。エッジ検出までは問題なく処理が行われているように見えましたが、エッジ検出を行った画像を追記させていただきたいと思います。 追記依頼お手数おかけしました。
tiitoi

2019/01/23 11:10

HoughLinesP() のパラメータの調整はしましたか?
mr_shirohige

2019/01/23 11:43

thresholdの値をいじったり、minLineLength等の値を追加してみるなどしましたが赤線が引かれる直線の位置が変化するだけで一本のみのままでした。 試したことの欄に追記させていただきます。
iwanote

2019/01/23 13:10

角度分解能が大きいのでは?
mr_shirohige

2019/01/23 15:46

thetaの数値を10刻みでさげてみたりしましたが実行結果に特に変化はありませんでした。
iwanote

2019/01/23 15:52

そちらではなくMath.PI/180のほうですね
mr_shirohige

2019/01/23 16:15

180の部分の数値を変更するということでよろしかったでしょうか?先ほどはその数値を変更していましたが…初心者ゆえ見当違いな発言でしたらご容赦ください
iwanote

2019/01/23 16:30

すみません見間違えてました合ってますね…すみません
guest

回答2

0

ベストアンサー

colとrowが逆ではないでしょうか.以下のC#コード(OpenCV for Unityを使用,Javaベースなので同じはず)で正しく検出できました.
人工画像で一本しか検出しないとは考えにくいので,パラメータよりも表示の方を疑うべきかと思います.

csharp

1int rows = linesMat.rows(); 2for (int i = 0; i < rows; i++){ 3 data = linesMat.get(i, 0); 4 pt1.x = data(i, 0)[0]; 5 pt1.y = data(i, 0)[1]; 6 pt2.x = data(i, 0)[2]; 7 pt2.y = data(i, 0)[3]; 8 line(bmpmat, pt1, pt2, new Scalar(255, 0, 0), 1); 9}

あと,for文の条件式で毎回メソッド呼ぶより事前に変数に格納しておく方が処理時間短くなると思います.

投稿2019/01/23 17:08

編集2019/01/23 17:20
Takaya901

総合スコア181

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

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

mr_shirohige

2019/01/23 17:32

こちらのコードを参考にさせていただいたところ、無事想定していた検出結果を得ることができました。 画像処理やプログラミングに関してまだまだ素人なため、精進したいと思います。 また何か質問した際、お目に止まれば回答していただければ幸いです。 非常に助かりました、回答ありがとうございました。
Takaya901

2019/01/23 18:01

Matの構造はややこしいので気をつけてください. お役に立ててよかったです.
guest

0

以下のコード、パラメータで検出できることを確認しました。
Python ですが、Java でも OpenCV の処理自体は同じはずなので、検出できるかと思います。

前処理

python

1import cv2 2import numpy as np 3 4img = cv2.imread('test.jpeg') 5# BGR -> グレースケール 6gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 7# ガウシアンフィルタ 8gauss = cv2.GaussianBlur(gray, (9, 9), 0) 9# Canny 10edges = cv2.Canny(gauss, 100, 150)

HoughLinesP() を使った直線検出

lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, 100, 10) lines = lines.squeeze(axis=1) # (NumLines, 1, 4) -> (NumLines, 4) dst = img.copy() for x1, y1, x2, y2 in lines: cv2.line(dst, (x1, y1), (x2, y2), (0, 0, 255), 1) cv2.imwrite('houghlinesp_result.png', dst)

イメージ説明

投稿2019/01/23 16:29

tiitoi

総合スコア21956

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

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

mr_shirohige

2019/01/23 17:41

ご回答ありがとうございます。 他の回答者様より、表示のコードのミスであるとご指摘いただき、参考にさせていただいたところ無事動作致しました。 ガウシアンフィルタ等の処理やpythonでのOpenCVの記述法は、後学のために参考にさせていただきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問