参考サイトを用いて写真の中にある名刺(紙)を拡大、抽出するアプリを作成したいと考えています。
実機で試したところ、透視変換の関数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
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/11/27 15:28
2018/11/28 01:13