ในช่วงไม่กี่ปีที่ผ่านมาประสิทธิภาพของโทรศัพท์มือถือโดยเฉลี่ยเพิ่มขึ้นอย่างมาก ไม่ว่าจะเป็นแรงม้าของ CPU หรือความจุ RAM ที่สูงขึ้นตอนนี้การทำงานหนักในการคำนวณบนฮาร์ดแวร์มือถือทำได้ง่ายขึ้น แม้ว่าเทคโนโลยีมือถือเหล่านี้จะมุ่งไปในทิศทางที่ถูกต้อง แต่ก็ยังมีอีกหลายอย่างที่ต้องทำบนแพลตฟอร์มมือถือโดยเฉพาะอย่างยิ่งเมื่อเกิดความจริงเสริมความจริงเสมือนและปัญญาประดิษฐ์
ความท้าทายที่สำคัญในการมองเห็นของคอมพิวเตอร์คือการตรวจจับวัตถุที่น่าสนใจในภาพ ตาและสมองของมนุษย์ทำงานได้อย่างยอดเยี่ยมและ จำลองสิ่งนี้ในเครื่องจักร ยังคงเป็นความฝัน ในช่วงหลายทศวรรษที่ผ่านมามีการพัฒนาแนวทางเพื่อเลียนแบบสิ่งนี้ในเครื่องจักรและกำลังดีขึ้นเรื่อย ๆ
ในบทช่วยสอนนี้เราจะสำรวจอัลกอริทึมที่ใช้ในการตรวจจับ blobs ในรูปภาพ เราจะใช้อัลกอริทึมจากไลบรารีโอเพนซอร์ส OpenCV เพื่อใช้งาน แอปพลิเคชัน iPhone ต้นแบบ ที่ใช้กล้องหลังเพื่อรับภาพและตรวจจับวัตถุที่อยู่ในนั้น
OpenCV เป็นไลบรารีโอเพนซอร์สที่ให้การใช้งานของวิสัยทัศน์คอมพิวเตอร์ที่สำคัญและอัลกอริทึมการเรียนรู้ของเครื่อง หากคุณต้องการติดตั้งแอพพลิเคชั่นเพื่อตรวจจับใบหน้าเล่นไพ่บนโต๊ะโป๊กเกอร์หรือแม้แต่แอพพลิเคชั่นง่ายๆสำหรับเพิ่มเอฟเฟกต์ให้กับรูปภาพโดยพลการ OpenCV ก็เป็นตัวเลือกที่ยอดเยี่ยม
OpenCV เขียนด้วยภาษา C / C ++ และมีไลบรารีของ Wrapper สำหรับแพลตฟอร์มหลักทั้งหมด ทำให้ง่ายต่อการใช้งานภายในไฟล์ สภาพแวดล้อม iOS . เพื่อใช้ภายใน Objective-C แอปพลิเคชัน iOS ดาวน์โหลดไฟล์ OpenCV iOS Framework จากเว็บไซต์ทางการ . โปรดตรวจสอบให้แน่ใจว่าคุณกำลังใช้ OpenCV เวอร์ชัน 2.4.11 สำหรับ iOS (ซึ่งบทความนี้ถือว่าคุณกำลังใช้งานอยู่) ซึ่งเป็นเวอร์ชันล่าสุด 3.0 มีการเปลี่ยนแปลงที่เข้ากันไม่ได้ในการจัดระเบียบไฟล์ส่วนหัว ข้อมูลรายละเอียดเกี่ยวกับวิธีการติดตั้งคือ บันทึกไว้ในเว็บไซต์ .
MSER ย่อมาจาก Maximally Stable Extremal Regions เป็นหนึ่งในหลายวิธีที่สามารถใช้ได้สำหรับการตรวจจับหยดภายในภาพ กล่าวง่ายๆคืออัลกอริทึมจะระบุชุดพิกเซลที่ต่อเนื่องกันซึ่งความเข้มของพิกเซลขอบเขตภายนอกสูงกว่า (ตามเกณฑ์ที่กำหนด) มากกว่าความเข้มของพิกเซลขอบเขตด้านใน ภูมิภาคดังกล่าวมีความเสถียรสูงสุดหากไม่เปลี่ยนแปลงมากนักในระดับความเข้มข้นที่แตกต่างกัน
แม้ว่าจำนวนอื่น ๆ อัลกอริทึมการตรวจจับหยด มีอยู่ MSER ถูกเลือกที่นี่เนื่องจากมีความซับซ้อนของ O (n log (log (n))) ที่ค่อนข้างเบาโดยที่ n คือจำนวนพิกเซลทั้งหมดบนภาพ อัลกอริทึมยังมีประสิทธิภาพในการเบลอและปรับขนาดซึ่งเป็นประโยชน์เมื่อต้องประมวลผลภาพที่ได้มาจากแหล่งข้อมูลแบบเรียลไทม์เช่นกล้องของโทรศัพท์มือถือ
สำหรับจุดประสงค์ของบทช่วยสอนนี้เราจะออกแบบไฟล์ ใบสมัคร เพื่อตรวจจับโลโก้ของ ApeeScape สัญลักษณ์นี้มีมุมที่คมชัดและนั่นอาจทำให้ใคร ๆ คิดว่าอัลกอริทึมการตรวจจับมุมที่มีประสิทธิภาพในการตรวจจับโลโก้ของ ApeeScape นั้นมีประสิทธิภาพเพียงใด ท้ายที่สุดแล้วอัลกอริทึมดังกล่าวใช้งานง่ายและเข้าใจง่าย แม้ว่าวิธีการตามมุมอาจมีอัตราความสำเร็จสูงเมื่อต้องตรวจจับวัตถุที่แยกจากพื้นหลังอย่างชัดเจน (เช่นวัตถุสีดำบนพื้นหลังสีขาว) แต่การตรวจจับ ApeeScape แบบเรียลไทม์ก็เป็นเรื่องยาก โลโก้ บนภาพในโลกแห่งความเป็นจริงซึ่งอัลกอริทึมจะตรวจจับมุมหลายร้อยมุมอย่างต่อเนื่อง
วิธีหลอกเว็บไซต์ให้คิดว่าคุณจ่ายเงิน
สำหรับแต่ละเฟรมของภาพที่แอปพลิเคชันได้มาจากกล้องนั้นจะถูกแปลงเป็นสีเทาก่อน ภาพโทนสีเทามีช่องสีเพียงช่องเดียว แต่จะมองเห็นโลโก้ได้ สิ่งนี้ทำให้อัลกอริทึมจัดการกับรูปภาพได้ง่ายขึ้นและลดจำนวนข้อมูลที่อัลกอริทึมต้องประมวลผลเพื่อให้ได้รับเพิ่มขึ้นเพียงเล็กน้อยหรือไม่มีเลย
ต่อไปเราจะใช้อัลกอริทึมการใช้งานของ OpenCV เพื่อแยก MSER ทั้งหมด จากนั้น MSER แต่ละตัวจะถูกทำให้เป็นมาตรฐานโดยการเปลี่ยนรูปสี่เหลี่ยมผืนผ้าที่มีขอบเขตต่ำสุดเป็นสี่เหลี่ยมจัตุรัส ขั้นตอนนี้มีความสำคัญเนื่องจากโลโก้อาจได้มาจากมุมและระยะทางที่แตกต่างกันและจะช่วยเพิ่มความทนทานต่อการบิดเบือนมุมมอง
นอกจากนี้ยังมีการคำนวณคุณสมบัติหลายประการสำหรับ MSER แต่ละตัว:
ในการตรวจจับโลโก้ของ ApeeScape ในรูปภาพคุณสมบัติของ MSER ทั้งหมดจะถูกเปรียบเทียบกับคุณสมบัติของโลโก้ ApeeScape ที่เรียนรู้ไปแล้ว สำหรับจุดประสงค์ของบทช่วยสอนนี้ความแตกต่างสูงสุดที่อนุญาตสำหรับแต่ละคุณสมบัติจะถูกเลือกในเชิงประจักษ์
บริษัทสามารถเป็นหุ้นส่วนได้หรือไม่
ในที่สุดภูมิภาคที่คล้ายกันมากที่สุดจะถูกเลือกให้เป็นผลลัพธ์
การใช้ OpenCV จาก iOS เป็นเรื่องง่าย หากคุณยังไม่ได้ดำเนินการต่อไปนี้เป็นโครงร่างโดยย่อของขั้นตอนที่เกี่ยวข้องในการตั้งค่า Xcode เพื่อสร้างแอปพลิเคชัน iOS และใช้ OpenCV ในนั้น:
สร้างชื่อโปรเจ็กต์ใหม่“ SuperCool Logo Detector” ในฐานะภาษาปล่อยให้ Objective-C เลือกไว้
เพิ่มไฟล์ Prefix Header (.pch) ใหม่และตั้งชื่อว่า PrefixHeader.pch
ไปที่โปรเจ็กต์“ SuperCool Logo Detector” Build Target และในแท็บ Build Settings ให้ค้นหาการตั้งค่า“ Prefix Headers” คุณสามารถค้นหาได้ในส่วนภาษา LLVM หรือใช้คุณสมบัติการค้นหา
เพิ่ม“ PrefixHeader.pch” ในการตั้งค่าส่วนหัวของคำนำหน้า
ณ จุดนี้หากคุณยังไม่ได้ติดตั้ง OpenCV สำหรับ iOS 2.4.11 ลงมือเลย
ลากและวางเฟรมเวิร์กที่ดาวน์โหลดลงในโปรเจ็กต์ ตรวจสอบ“ กรอบงานและไลบรารีที่เชื่อมโยง” ในการตั้งค่าเป้าหมายของคุณ (ควรเพิ่มโดยอัตโนมัติ แต่จะดีกว่าเพื่อความปลอดภัย)
นอกจากนี้เชื่อมโยงกรอบงานต่อไปนี้:
เปิด“ PrefixHeader.pch” และเพิ่ม 3 บรรทัดต่อไปนี้:
ขายโดรนไปแล้วกี่ตัว
#ifdef __cplusplus #include #endif”
เปลี่ยนนามสกุลของไฟล์โค้ดที่สร้างขึ้นโดยอัตโนมัติจาก“ .m” ถึง“ .mm”. OpenCV เขียนด้วย C ++ และด้วย * .mm คุณกำลังบอกว่าคุณจะใช้ Objective-C ++
นำเข้า“ opencv2 / highgui / cap_ios.h” ใน ViewController.h และเปลี่ยน ViewController ให้สอดคล้องกับโปรโตคอล CvVideoCameraDelegate:
#import
เปิด Main.storyboard และวาง UIImageView บนตัวควบคุมมุมมองเริ่มต้น
สร้างเต้าเสียบให้กับ ViewController.mm ชื่อ“ imageView”
สร้างตัวแปร“ กล้อง CvVideoCamera *;” ใน ViewController.h หรือ ViewController.mm และเริ่มต้นด้วยการอ้างอิงถึงกล้องหลัง:
camera = [[CvVideoCamera alloc] initWithParentView: _imageView]; camera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack; camera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480; camera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait; camera.defaultFPS = 30; camera.grayscaleMode = NO; camera.delegate = self;
หากคุณสร้างโครงการตอนนี้ Xcode จะเตือนว่าคุณไม่ได้ใช้เมธอด“ processImage” จาก CvVideoCameraDelegate สำหรับตอนนี้และเพื่อความเรียบง่ายเราเพียงแค่ได้รับภาพจากกล้องและซ้อนทับด้วยข้อความง่ายๆ:
[camera start];
ตอนนี้หากคุณเรียกใช้แอปพลิเคชันแอปพลิเคชันจะขออนุญาตจากคุณในการเข้าถึงกล้อง จากนั้นคุณจะเห็นวิดีโอจากกล้อง
ในเมธอด 'processImage' ให้เพิ่มสองบรรทัดต่อไปนี้:
วิธีทำตู้โชว์
const char* str = [@'ApeeScape' cStringUsingEncoding: NSUTF8StringEncoding]; cv::putText(image, str, cv::Point(100, 100), CV_FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 0, 255));
ที่สวยมาก ๆ เลยค่ะ ตอนนี้คุณมีแอปพลิเคชั่นง่ายๆที่วาดข้อความ“ ApeeScape” บนภาพจากกล้อง ตอนนี้เราสามารถสร้างแอปพลิเคชั่นตรวจจับโลโก้เป้าหมายของเราจากอันที่ง่ายกว่านี้ได้ เพื่อความกะทัดรัดในบทความนี้เราจะพูดถึงกลุ่มโค้ดเพียงไม่กี่กลุ่มที่มีความสำคัญต่อการทำความเข้าใจวิธีการทำงานของแอปพลิเคชันโดยรวม โค้ดบน GitHub มีความคิดเห็นจำนวนพอสมควรเพื่ออธิบายว่าแต่ละส่วนทำอะไร
การเขียนโปรแกรมคอมพิวเตอร์ c++
เนื่องจากแอปพลิเคชันมีเพียงจุดประสงค์เดียวเพื่อตรวจจับโลโก้ของ ApeeScape ทันทีที่เปิดตัวฟีเจอร์ MSER จะถูกดึงออกมาจากภาพเทมเพลตที่กำหนดและค่าจะถูกเก็บไว้ในหน่วยความจำ:
cv::Mat logo = [ImageUtils cvMatFromUIImage: templateImage]; //get gray image cv::Mat gray; cvtColor(logo, gray, CV_BGRA2GRAY); //mser with maximum area is std::vector maxMser = [ImageUtils maxMser: &gray]; //get 4 vertices of the maxMSER minrect cv::RotatedRect rect = cv::minAreaRect(maxMser); cv::Point2f points[4]; rect.points(points); //normalize image cv::Mat M = [GeometryUtil getPerspectiveMatrix: points toSize: rect.size]; cv::Mat normalizedImage = [GeometryUtil normalizeImage: &gray withTranformationMatrix: &M withSize: rect.size.width]; //get maxMser from normalized image std::vector normalizedMser = [ImageUtils maxMser: &normalizedImage]; //remember the template self.logoTemplate = [[MSERManager sharedInstance] extractFeature: &normalizedMser]; //store the feature [self storeTemplate];
แอปพลิเคชันมีเพียงหน้าจอเดียวที่มีปุ่มเริ่ม / หยุดและข้อมูลที่จำเป็นทั้งหมดเนื่องจาก FPS และจำนวน MSER ที่ตรวจพบจะถูกวาดโดยอัตโนมัติบนรูปภาพ ตราบเท่าที่แอปพลิเคชันไม่หยุดทำงานสำหรับทุกเฟรมภาพในกล้องจะเรียกใช้เมธอด processImage ต่อไปนี้:
-(void)processImage:(cv::Mat &)image { cv::Mat gray; cvtColor(image, gray, CV_BGRA2GRAY); std::vector msers; [[MSERManager sharedInstance] detectRegions: gray intoVector: msers]; if (msers.size() == 0) { return; }; std::vector *bestMser = nil; double bestPoint = 10.0; std::for_each(msers.begin(), msers.end(), [&] (std::vector &mser) { MSERFeature *feature = [[MSERManager sharedInstance] extractFeature: &mser]; if(feature != nil) { if([[MLManager sharedInstance] isApeeScapeLogo: feature] ) { double tmp = [[MLManager sharedInstance] distance: feature ]; if ( bestPoint > tmp ) { bestPoint = tmp; bestMser = &mser; } } } }); if (bestMser) { NSLog(@'minDist: %f', bestPoint); cv::Rect bound = cv::boundingRect(*bestMser); cv::rectangle(image, bound, GREEN, 3); } else { cv::rectangle(image, cv::Rect(0, 0, W, H), RED, 3); } // Omitted debug code [FPS draw: image]; }
โดยพื้นฐานแล้ววิธีนี้จะสร้างสำเนาสีเทาของภาพต้นฉบับ ระบุ MSER ทั้งหมดและแยกคุณสมบัติที่เกี่ยวข้องคะแนน MSER แต่ละตัวมีความคล้ายคลึงกับเทมเพลตและเลือกสิ่งที่ดีที่สุด สุดท้ายจะวาดขอบเขตสีเขียวรอบ ๆ MSER ที่ดีที่สุดและวางซ้อนภาพด้วยข้อมูลเมตา
ด้านล่างนี้เป็นคำจำกัดความของคลาสที่สำคัญบางอย่างและวิธีการในแอปพลิเคชันนี้ วัตถุประสงค์ของพวกเขาอธิบายไว้ในความคิดเห็น
/* This static class provides perspective transformation function */ @interface GeometryUtil : NSObject /* Return perspective transformation matrix for given points to square with origin [0,0] and with size (size.width, size.width) */ + (cv::Mat) getPerspectiveMatrix: (cv::Point2f[]) points toSize: (cv::Size2f) size; /* Returns new perspecivly transformed image with given size */ + (cv::Mat) normalizeImage: (cv::Mat *) image withTranformationMatrix: (cv::Mat *) M withSize: (float) size; @end
/* Singelton class providing function related to msers */ @interface MSERManager : NSObject + (MSERManager *) sharedInstance; /* Extracts all msers into provided vector */ - (void) detectRegions: (cv::Mat &) gray intoVector: (std::vector &) vector; /* Extracts feature from the mser. For some MSERs feature can be NULL !!! */ - (MSERFeature *) extractFeature: (std::vector *) mser; @end
/* This singleton class wraps object recognition function */ @interface MLManager : NSObject + (MLManager *) sharedInstance; /* Stores feature from the biggest MSER in the templateImage */ - (void) learn: (UIImage *) templateImage; /* Sum of the differences between logo feature and given feature */ - (double) distance: (MSERFeature *) feature; /* Returns true if the given feature is similar to the one learned from the template */ - (BOOL) isApeeScapeLogo: (MSERFeature *) feature; @end
หลังจากเชื่อมต่อทุกอย่างเข้าด้วยกันแล้วด้วยแอปพลิเคชันนี้คุณควรจะสามารถใช้กล้องของอุปกรณ์ iOS ของคุณเพื่อตรวจจับโลโก้ของ ApeeScape จากมุมและทิศทางต่างๆ
ในบทความนี้เราได้แสดงให้เห็นว่าการตรวจจับวัตถุง่ายๆจากภาพโดยใช้ OpenCV นั้นง่ายเพียงใด รหัสทั้งหมดคือ พร้อมใช้งานบน GitHub . อย่าลังเลที่จะแยกและส่งคำขอผลักดันเนื่องจากยินดีต้อนรับการมีส่วนร่วม
ตามที่เป็นจริงสำหรับปัญหาการเรียนรู้ของเครื่องอัตราความสำเร็จของการตรวจจับโลโก้ในแอปพลิเคชันนี้อาจเพิ่มขึ้นโดยใช้ชุดคุณสมบัติที่แตกต่างกันและวิธีการที่แตกต่างกันสำหรับการจำแนกประเภทวัตถุ อย่างไรก็ตามฉันหวังว่าบทความนี้จะช่วยให้คุณเริ่มต้นด้วยการตรวจจับวัตถุโดยใช้ MSER และการประยุกต์ใช้เทคนิคการมองเห็นด้วยคอมพิวเตอร์โดยทั่วไป