CIDetector 邊緣識(shí)別

CoreImageCIDetector.h自帶了四種識(shí)別功能

/ * 人臉識(shí)別 */
CORE_IMAGE_EXPORT NSString* const CIDetectorTypeFace NS_AVAILABLE(10_7, 5_0);

/ * 矩形邊緣識(shí)別 */
CORE_IMAGE_EXPORT NSString* const CIDetectorTypeRectangle NS_AVAILABLE(10_10, 8_0);

/* 二維碼識(shí)別 */
CORE_IMAGE_EXPORT NSString* const CIDetectorTypeQRCode NS_AVAILABLE(10_10, 8_0);

/* 文本識(shí)別 */
#if __OBJC2__
CORE_IMAGE_EXPORT NSString* const CIDetectorTypeText NS_AVAILABLE(10_11, 9_0);

接下來(lái)用CIDetectorTypeRectangle對(duì)圖片的矩形狀邊緣進(jìn)行識(shí)別宙帝,效果圖如下 (Demo鏈接文章底部已給出

識(shí)別邊緣
截取

部分代碼:

  • 初始化一個(gè)高精度的識(shí)別器
// 高精度邊緣識(shí)別器
- (CIDetector *)highAccuracyRectangleDetector
{
    static CIDetector *detector = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^
                  {
                      detector = [CIDetector detectorOfType:CIDetectorTypeRectangle context:nil options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}];
                  });
    return detector;
}
  • 調(diào)用照相機(jī)捕獲攝像頭圖像
NSArray *possibleDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    AVCaptureDevice *device = [possibleDevices firstObject];
    if (!device) return;
    
    _imageDedectionConfidence = 0.0;
    
    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    self.captureSession = session;
    [session beginConfiguration];
    self.captureDevice = device;
    
    NSError *error = nil;
    AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    session.sessionPreset = AVCaptureSessionPresetPhoto;
    [session addInput:input];
    
    AVCaptureVideoDataOutput *dataOutput = [[AVCaptureVideoDataOutput alloc] init];
    [dataOutput setAlwaysDiscardsLateVideoFrames:YES];
    [dataOutput setVideoSettings:@{(id)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA)}];
    [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
    [session addOutput:dataOutput];
    
    self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    [session addOutput:self.stillImageOutput];
    
    AVCaptureConnection *connection = [dataOutput.connections firstObject];
    [connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
  • 還需要有個(gè)顯示已捕獲圖像的容器
 self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    GLKView *view = [[GLKView alloc] initWithFrame:self.bounds];
    view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    view.translatesAutoresizingMaskIntoConstraints = YES;
    view.context = self.context;
    view.contentScaleFactor = 1.0f;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    [self insertSubview:view atIndex:0];
    _glkView = view;
    glGenRenderbuffers(1, &_renderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
    
    //圖像將繪制進(jìn)_coreImageContext內(nèi)
    _coreImageContext = [CIContext contextWithEAGLContext:self.context];
    [EAGLContext setCurrentContext:self.context];
  • 遵循AVCaptureVideoDataOutputSampleBufferDelegate代理,捕獲到圖像之后株憾,會(huì)調(diào)用以下方法
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection

調(diào)用CIDetector進(jìn)行識(shí)別,并且獲取最大不規(guī)則四邊形

// 從緩沖區(qū)中獲取CIImage
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer];
 // 用高精度邊緣識(shí)別器 識(shí)別特征
NSArray <CIFeature *>*features = [[self highAccuracyRectangleDetector] featuresInImage:image];
// 選取特征列表中最大的不規(guī)則四邊形
 _borderDetectLastRectangleFeature = [self biggestRectangleInRectangles:features];
  • 識(shí)別到邊緣之后使用CAShapeLayer將邊緣繪制并顯示
// 繪制邊緣檢測(cè)圖層
- (void)drawBorderDetectRectWithImageRect:(CGRect)imageRect topLeft:(CGPoint)topLeft topRight:(CGPoint)topRight bottomLeft:(CGPoint)bottomLeft bottomRight:(CGPoint)bottomRight
{
    
    if (!_rectOverlay) {
        _rectOverlay = [CAShapeLayer layer];
        _rectOverlay.fillRule = kCAFillRuleEvenOdd;
        _rectOverlay.fillColor = [UIColor colorWithRed:73/255.0 green:130/255.0 blue:180/255.0 alpha:0.4].CGColor;
        _rectOverlay.strokeColor = [UIColor whiteColor].CGColor;
        _rectOverlay.lineWidth = 5.0f;
    }
    if (!_rectOverlay.superlayer) {
        self.layer.masksToBounds = YES;
        [self.layer addSublayer:_rectOverlay];
    }

    // 將圖像空間的坐標(biāo)系轉(zhuǎn)換成uikit坐標(biāo)系
    TransformCIFeatureRect featureRect = [self transfromRealRectWithImageRect:imageRect topLeft:topLeft topRight:topRight bottomLeft:bottomLeft bottomRight:bottomRight];
    
    // 邊緣識(shí)別路徑
    UIBezierPath *path = [UIBezierPath new];
    [path moveToPoint:featureRect.topLeft];
    [path addLineToPoint:featureRect.topRight];
    [path addLineToPoint:featureRect.bottomRight];
    [path addLineToPoint:featureRect.bottomLeft];
    [path closePath];
    // 背景遮罩路徑
    UIBezierPath *rectPath  = [UIBezierPath bezierPathWithRect:CGRectMake(-5,
                                                                          -5,
                                                                          self.frame.size.width + 10,
                                                                          self.frame.size.height + 10)];
    [rectPath setUsesEvenOddFillRule:YES];
    [rectPath appendPath:path];
    _rectOverlay.path = rectPath.CGPath;
}

即可顯示出實(shí)時(shí)識(shí)別的效果了

  • 最后拍照之后的裁剪较曼,使用該濾鏡將識(shí)別出的不規(guī)則四邊形轉(zhuǎn)換成矩形须尚,即可轉(zhuǎn)換成正正方方的矩形了
/// 將任意四邊形轉(zhuǎn)換成長(zhǎng)方形
- (CIImage *)correctPerspectiveForImage:(CIImage *)image withFeatures:(CIRectangleFeature *)rectangleFeature
{
    NSMutableDictionary *rectangleCoordinates = [NSMutableDictionary new];
    rectangleCoordinates[@"inputTopLeft"] = [CIVector vectorWithCGPoint:rectangleFeature.topLeft];
    rectangleCoordinates[@"inputTopRight"] = [CIVector vectorWithCGPoint:rectangleFeature.topRight];
    rectangleCoordinates[@"inputBottomLeft"] = [CIVector vectorWithCGPoint:rectangleFeature.bottomLeft];
    rectangleCoordinates[@"inputBottomRight"] = [CIVector vectorWithCGPoint:rectangleFeature.bottomRight];
    return [image imageByApplyingFilter:@"CIPerspectiveCorrection" withInputParameters:rectangleCoordinates];
}

// TODO : 識(shí)別出邊緣之后,可以手動(dòng)設(shè)置邊緣范圍

手動(dòng)設(shè)置邊緣范圍

Demo地址: github傳送門(mén):https://github.com/madaoCN/MADRectDetect 好心人點(diǎn)下Star唄

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末假消,一起剝皮案震驚了整個(gè)濱河市柠并,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌富拗,老刑警劉巖臼予,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異啃沪,居然都是意外死亡粘拾,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)创千,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)缰雇,“玉大人,你說(shuō)我怎么就攤上這事追驴⌒涤矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵殿雪,是天一觀的道長(zhǎng)暇咆。 經(jīng)常有香客問(wèn)我,道長(zhǎng)丙曙,這世上最難降的妖魔是什么爸业? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮河泳,結(jié)果婚禮上沃呢,老公的妹妹穿的比我還像新娘。我一直安慰自己拆挥,他們只是感情好薄霜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布某抓。 她就那樣靜靜地躺著,像睡著了一般惰瓜。 火紅的嫁衣襯著肌膚如雪否副。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,604評(píng)論 1 305
  • 那天崎坊,我揣著相機(jī)與錄音备禀,去河邊找鬼。 笑死奈揍,一個(gè)胖子當(dāng)著我的面吹牛曲尸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼凭语!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起昆箕,我...
    開(kāi)封第一講書(shū)人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎租冠,沒(méi)想到半個(gè)月后鹏倘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顽爹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年纤泵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镜粤。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夕吻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出繁仁,到底是詐尸還是另有隱情,我是刑警寧澤归园,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布黄虱,位于F島的核電站,受9級(jí)特大地震影響庸诱,放射性物質(zhì)發(fā)生泄漏捻浦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一桥爽、第九天 我趴在偏房一處隱蔽的房頂上張望朱灿。 院中可真熱鬧,春花似錦钠四、人聲如沸盗扒。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)侣灶。三九已至甸祭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間褥影,已是汗流浹背池户。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凡怎,地道東北人校焦。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像统倒,于是被迫代替她去往敵國(guó)和親寨典。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容