概述: 本節主要結合降噪,色域轉換,二值化,邊緣檢測及獲取輪廓等函數,實現對身份證的邊緣位置檢測;
一: 本節目的:
先展示一下效果:
Snip20171109_1.png
本人真實身份證(留個眼睛看著你們...),聽說最近有一鍵卸妝的軟件,唉,你要真給我卸了也就認命了;不扯淡,說正題,這個效果有什么用呢?
說實話我也不知道,恰好最近有這么個需求而已,要求如下:
檢測身份證,銀行卡,營業執照等等....要在UI上提示用戶拍攝時目標證件是否在要求的框框范圍之內,不能超出也不能太小,嗯,沒毛病,就是這樣的;
二.實現過程:
Snip20171109_8.png
三. 代碼實現:
#import <opencv2/highgui/cap_ios.h>
...
...
using namespace cv;
using namespace std;
double minThreshold = 10;
double ratioThreshold = 3;
- (void)viewDidLoad{
[super viewDidLoad];
Mat sourceMatImage;
UIImageToMat(self.imageView.image, sourceMatImage);
// 降噪
blur(sourceMatImage, sourceMatImage, cv::Size(3,3));
// 轉為灰度圖
cvtColor(sourceMatImage, sourceMatImage, CV_BGR2GRAY);
// 二值化
threshold(sourceMatImage, sourceMatImage, 190, 255, CV_THRESH_BINARY);
// 檢測邊界
Canny(sourceMatImage, sourceMatImage, minThreshold * ratioThreshold, minThreshold);
// 獲取輪廓
std::vector<std::vector<cv::Point>> contours;
findContours(sourceMatImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
/*
* 重新繪制輪廓
*/
// 初始化一個8UC3的純黑圖像
Mat dstImg(sourceMatImage.size(), CV_8UC3, Scalar::all(0));
// 用于存放輪廓折線點集
std::vector<std::vector<cv::Point>> contours_poly(contours.size());
// STL遍歷
std::vector<std::vector<cv::Point>>::const_iterator itContours = contours.begin();
std::vector<std::vector<cv::Point>>::const_iterator itContourEnd = contours.end();
// ++i 比 i++ 少一次內存寫入,性能更高
for (int i=0 ; itContours != itContourEnd; ++itContours,++i) {
approxPolyDP(Mat(contours[i]), contours_poly[i], 15, true);
// 繪制處理后的輪廓,可以一段一段繪制,也可以一次性繪制
// drawContours(dstImg, contours_poly, i, Scalar(208, 19, 29), 8, 8);
}
/*如果C++ 基礎不夠,可以使用 for 循環
* for (int i = 0; i < contours.size(); i ++) {
* approxPolyDP(contours[i] , contours_poly[i], 5, YES);
* }
*/
// 繪制處理后的輪廓,一次性繪制
drawContours(dstImg, contours_poly, -1, Scalar(208, 19, 29), 8, 8);
// 顯示繪制結果
self.desImageView.image = MatToUIImage(dstImg);
補充:截取的邊界應該去除透視投影:
CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] );
CV_EXPORTS_W void warpPerspective( InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags=INTER_LINEAR,
int borderMode=BORDER_CONSTANT,
const Scalar& borderValue=Scalar()
);