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

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

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

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

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

670閲覧

warpPerspectiveを使って画像を透視変換して拡大したい

akito0705

総合スコア23

OpenCV

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

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/11/22 13:45

編集2018/11/23 06:43

参考サイトを用いて写真の中にある名刺(紙)を拡大、抽出するアプリを作成したいと考えています。
実機で試したところ、透視変換の関数warpPerspectiveの使い方がよくわからず、一色に塗り潰された画像が出力されてしまいます。
短形取得、描画まではできているのですが、その先のcontours->point2fへの変換など座標の扱い方がわかりません。src,dstに何を入れればいいのか、間違えがあればその指摘をお願いします。
問題の部分はOpenCVWrapper.mmの一番下の部分です。

よろしくお願いします。

ViewController.swift

1import UIKit 2 3class ViewController: UIViewController, UIImagePickerControllerDelegate, 4UINavigationControllerDelegate{ 5 6 @IBOutlet var cameraView : UIImageView! 7 @IBOutlet var label : UILabel! 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 label.text = "Tap the [Start] to take a picture" 12 13 14 } 15 16 // カメラの撮影開始 17 @IBAction func startCamera(_ sender : AnyObject) { 18 19 let sourceType:UIImagePickerController.SourceType = 20 UIImagePickerController.SourceType.camera 21 // カメラが利用可能かチェック 22 if UIImagePickerController.isSourceTypeAvailable( 23 UIImagePickerController.SourceType.camera){ 24 // インスタンスの作成 25 let cameraPicker = UIImagePickerController() 26 cameraPicker.sourceType = sourceType 27 cameraPicker.delegate = self 28 self.present(cameraPicker, animated: true, completion: nil) 29 30 } 31 else{ 32 label.text = "error" 33 34 } 35 } 36 37 // 撮影が完了時した時に呼ばれる 38 func imagePickerController(_ imagePicker: UIImagePickerController, 39 didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){ 40 41 if let pickedImage = info[.originalImage] 42 as? UIImage { 43 44 cameraView.contentMode = .scaleAspectFit 45 cameraView.image = pickedImage 46 47 } 48 49 //閉じる処理 50 imagePicker.dismiss(animated: true, completion: nil) 51 label.text = "Tap the [Save] to save a picture" 52 53 } 54 55 // 撮影がキャンセルされた時に呼ばれる 56 func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { 57 picker.dismiss(animated: true, completion: nil) 58 label.text = "Canceled" 59 } 60 61 62 // 写真を保存 63 @IBAction func savePicture(_ sender : AnyObject) { 64 let image:UIImage! = cameraView.image 65 66 if image != nil { 67 UIImageWriteToSavedPhotosAlbum( 68 image, 69 self, 70 #selector(ViewController.image(_:didFinishSavingWithError:contextInfo:)), 71 nil) 72 } 73 else{ 74 label.text = "image Failed !" 75 } 76 77 } 78 79 // 書き込み完了結果の受け取り 80 @objc func image(_ image: UIImage, 81 didFinishSavingWithError error: NSError!, 82 contextInfo: UnsafeMutableRawPointer) { 83 84 if error != nil { 85 print(error.code) 86 label.text = "Save Failed !" 87 } 88 else{ 89 label.text = "Save Succeeded" 90 } 91 } 92 93 // アルバムを表示 94 @IBAction func showAlbum(_ sender : AnyObject) { 95 let sourceType:UIImagePickerController.SourceType = 96 UIImagePickerController.SourceType.photoLibrary 97 98 if UIImagePickerController.isSourceTypeAvailable( 99 UIImagePickerController.SourceType.photoLibrary){ 100 // インスタンスの作成 101 let cameraPicker = UIImagePickerController() 102 cameraPicker.sourceType = sourceType 103 cameraPicker.delegate = self 104 self.present(cameraPicker, animated: true, completion: nil) 105 106 label.text = "Tap the [Start] to save a picture" 107 } 108 else{ 109 label.text = "error" 110 111 } 112 113 } 114 115 //画像変換 116 @IBAction func photochange(_ sender : AnyObject) { 117 cameraView.image = OpenCVWrapper.makeGray(from: cameraView.image) 118 } 119 120}

OpenCVWrapper.mm

1#import <opencv2/opencv.hpp> 2#import <opencv2/imgcodecs/ios.h> 3#import "OpenCVWrapper.h" 4 5@implementation OpenCVWrapper 6 7+(NSString *)openCVVersionString{ 8 return [NSString stringWithFormat: @"openCV Version %s", CV_VERSION]; 9} 10 11+(UIImage * )makeGrayFromImage:(UIImage *)image{ 12 cv::Mat imageMat; 13 UIImageToMat(image, imageMat); 14 15 if(imageMat.channels() == 1)return image; 16 17 cv::Mat grayMat; 18 cv::cvtColor(imageMat, grayMat, cv::COLOR_BGR2GRAY); 19 cv::threshold(grayMat, grayMat, 200, 255, cv::THRESH_TOZERO_INV); 20 cv::bitwise_not(grayMat, grayMat); 21 cv::threshold(grayMat, grayMat, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU); 22 cv::Point finalpt; 23 24 std::vector<std::vector<cv::Point>> contours; 25 std::vector<cv::Vec4i> hierarchy; 26 cv::findContours(grayMat, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_TC89_L1); 27 int max_level = 0; 28 for(int i = 0; i < contours.size(); i++) { 29 // ある程度の面積が有るものだけに絞る 30 double a = contourArea(contours[i],false); 31 if(a > 15000) { 32 //輪郭を直線近似する 33 std::vector<cv::Point> approx; 34 cv::approxPolyDP(cv::Mat(contours[i]), approx, 0.01 * cv::arcLength(contours[i], true), true); 35 // 矩形のみ取得 36 if (approx.size() == 4) { 37 cv::drawContours(imageMat, contours, i, cv::Scalar(255, 0, 0, 255), 3, 16, hierarchy, max_level); 38 } 39 } 40 } 41 42 cv::Point2f src[4]; // 変換元 43 cv::Point2f dst[4]; // 変換先 44 cv::Mat perspective_matrix = cv::getPerspectiveTransform(src, dst); 45 cv::warpPerspective(imageMat, imageMat, perspective_matrix, imageMat.size(), cv::INTER_LINEAR); 46 return MatToUIImage(imageMat); 47} 48 49@end

OpenCVWrapper.h

1#import <Foundation/Foundation.h> 2#import <UIKit/UIKit.h> 3 4 5 6@interface OpenCVWrapper : NSObject 7+(NSString * ) openCVVersionString; 8 9+(UIImage * )makeGrayFromImage:(UIImage * )image; 10@end

参考サイト
https://dev.classmethod.jp/smartphone/avfoundation-opencv-findcontours/
https://i-app-tec.com/ios/camera.html

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

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

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

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

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

guest

回答1

0

ベストアンサー

(私の知らない言語ですが)コードを見た感じ,
src,dst共に,まともな値が入れられていないように見えます.

  • srcには元の画像上における名刺の四隅の座標(approxPolyDPで得られた座標かな)
  • dstには,「拡大、抽出」した結果の四隅座標(例えば,変換結果用の画像バッファの四隅の座標とか)

を入れたら良い感じになりませんか?

投稿2018/11/26 06:22

fana

総合スコア11634

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

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

akito0705

2018/11/27 15:28

回答ありがとうございます。 srcに入れる座標ですが、contoursからsrcへ入れたいのですが、std::vector<std::vector<cv::Point>>からPoint2fに入れる方法がわかりません。 また、dstですが、これは最大サイズにしたいのですが指定する座標がわかりません。 よろしくお願いします。
fana

2018/11/28 01:13

> srcに入れる座標 approxが4点の座標なのではないのでしょうか? > dst 出力画像の四隅の座標を使うだけではダメなのですか? (リファレンスを見た感じだとwarpPerspectiveはインプレースで使えないっぽいので結果用の画像を用意する必要があるように思います)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問