I'm trying to implement dlib's face landmark detection for an iOS application.
On dlib's example they initialize a shape_predictor as such:
// And we also need a shape_predictor. This is the tool that will predict face
// landmark positions given an image and face bounding box. Here we are just
// loading the model from the shape_predictor_68_face_landmarks.dat file you gave
// as a command line argument.
shape_predictor sp;
deserialize(argv[1]) >> sp;
I'm trying to do the same in Objective-C and have gotten this far:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"shape_predictor_68_face_landmarks" ofType:#"dat"];
NSData *myData = [NSData dataWithContentsOfFile:filePath];
Doing the following gives me an error of "Receiver type 'dlib::shape_predictor' is not an Objective-C class"
sp = [dlib::shape_predictor deserialize:myData];
Assuming that you have setup the dlib library correctly in the project (and included the source.cpp file), you need a .mm file (Objective-C++) in which you can do the following:
#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing/render_face_detections.h>
#include <dlib/image_processing.h>
#include <dlib/opencv.h>
#include <dlib/image_io.h>
Then you can load the required dlib classes and use them with regular C++ syntax.
Here is an example:
dlib::frontal_face_detector detector = dlib::get_frontal_face_detector();
dlib::shape_predictor shapePredictor;
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *landmarkdat = [[NSString alloc] initWithFormat:#"%#/%s", mainBundle.bundlePath,"shape_predictor_68_face_landmarks.dat"];
dlib::deserialize(landmarkdat.UTF8String) >> shapePredictor;
Note: In my project I have added shape_predictor_68_face_landmarks.dat as a bundle resource in Project->Target->Build Phrases->Copy bundle resources and checked the copy button.
Related
I am developing an iOs application in which I have implemented the Dlib library to get the facial landmark points in an image. Below is the code I have implemented.
dlib::frontal_face_detector detector = dlib::get_frontal_face_detector();
dlib::shape_predictor shapePredictor;
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *landmarkdat = [[NSString alloc] initWithFormat:#"%#/%s",
mainBundle.bundlePath,"shape_predictor_68_face_landmarks.dat"];
dlib::deserialize(landmarkdat.UTF8String) >> shapePredictor;
dlib::array2d<dlib::rgb_pixel> img;
dlib::load_image(img,"001.png" );
But when I run the code in xcode 8.3 I am getting error.dlib::image_load_error: Unable to open file
You need to provide bundle path for that image which worked for me.
NSString *imagePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"jpg"];
std::string fileName = [imagePath UTF8String];
dlib::array2d<unsigned char> img;
load_image(img, fileName);
Note : Add images directly to bundle dont add images to asset folder.
I have a level editor for my iOS App and it's running on OS X. It saves the levels in an archived NSData-Object. These files are inside my apps bundle and I try to load them on the iOS app using:
NSString* path_ = [dictionary_ objectForKey:kWDLevelController_Level_PathKey];
NSString* sourcePath_ = [[NSBundle mainBundle] pathForResource:path_ ofType:#"wds"];
NSData* data_ = [NSData dataWithContentsOfFile:sourcePath_
options:NSDataReadingMappedIfSafe error:&error];
dataSource_ = [NSKeyedUnarchiver unarchiveObjectWithData:data_];
The returned NSData object is empty. I checked the path of the NSData-File inside the bundle and it's correct. I guess that it's the problem that the file was created on OS X and that I want to deserialize it on iOS.
Is there a way to do this? Or do I have to write my own serialization class or use any third-party?
I am attempting to load image files as an NSString, but all of them come up nil using this code:
NSString *path = [[NSBundle mainBundle] pathForResource:[NSString stringWithUTF8String:name.data()] ofType:nil];
NSString *da = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
I am able to load many files, but all JPEG and PNG files fail for some reason. I thought it might have something to do with encoding so I switched it to usedEncoding, but it still didn't work.
What am I missing?
EDIT:
I have been making an iOS/Android cross platform OpenGL graphics library in C++. Everything works except texture loading. Any file loading from disk goes through one function that is abstracted between systems. I need the image file in an STL string, so that I can pass it to an image parsing library to get the raw pixel data.
I just think that it's reduculous that the function I have can open any file except images.
If you run your code, passing an NSError instance instead of nil,
NSError *error = nil;
NSString *string = [NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:&error];
you will see that stringWithContentsOfFile cannot open the image file, returning nil and the error given is:
Error Domain=NSCocoaErrorDomain Code=261 "The operation couldn’t be completed. (Cocoa error 261.)"...
Cocoa error 261 is NSFileReadInapplicableStringEncodingError which means the encoding of the file is different from the one you are passing (NSUTF8StringEncoding). But I have tried with the other encodings, and none works for PNG files.
You can still achieve what you want by loading the file as a UIImage and then converting the UIImage into a Base64 string.
Since iOS 7, this is easier because you can use the built in method base64EncodedStringWithOptions:
// Load the image and convert it to NSData
UIImage *image = [UIImage imageNamed:#"yourImageName"];
NSData *imageData = UIImagePNGRepresentation(image);
// You can use the equivalent UIImageJPEGRepresentation() for JPEG images
// Convert NSData to a Base64 NSString
NSString *base64ImageString = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
Previous to iOS 7, you can do the exact same thing but you will have to implement your own Base64 encoding method (Or import any of the many already available, eg. nicklockwood/Base64).
I am trying to create a TIFF image from a UIImage. I looked into Apple's docs but could not find any information.
Can anyone help me and explain how to create a TIFF image on an iPad?
It seems to me that ImageMagick is way overkill just to write tiffs. Why not build libtiff? iOS is supported from it, and is what most software packages use to write tiffs (including ImageMagick).
You can even use the libtiff.a file from the ImageMagick link above. Just install the lib and tiff headers into your project.
EDIT:
Here is a nice tutorial showing you how to write a tiff once you have installed libtiff. The second part of the tutorial shows you how to control the compression.
I feel like this answer is a little late, but in case someone else wants to know how to do this, I think you'll find the following will do the trick:
NSMutableData *mData = [NSMutableData dataWithCapacity:SOME_BIG_NUMBER];
CGImageDestinationRef myImageDest = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)(mData), kUTTypeTIFF, 1, NULL);
CGImageDestinationAddImage(myImageDest,image.CGImage, NULL);
CGImageDestinationFinalize(myImageDest);
CFRelease(myImageDest);
The mData will then hold NSData encoding of a TIFF file which you can then store to the disk, upload to a server, whatever...
You might need to include MobileCoreServices and ImageIO frameworks...
Paul
ImageMagick has been compiled for iOS and allows for handling of TIFF images. The instructions can be found here:
Link
There is also a Sample Project that illustrates how to integrate this functionality into your application. It should be noted that including this library takes several steps - and the instructions are included in the link above.
SETTING UP A PROJECT FOR IMAGEMAGICK
First, download the latest version (from the first link above) with libs in the name. This includes pre-compiled versions of the needed frameworks. Unzip the contents of this file. Next, right-click Frameworks in your iOS projects and select the option to Add Files. Add each of the files with the .a extension. You should have something resembling this:
Next, you'll need to add the proper header search paths. Go to the Build Settings for your project and search for Header Search Paths. Select this and add a new search path that corresponds to where the include directory is (from the download). Don't add this just for debug or release, but for all. You should now have something that looks like this:
Now you should be able to include and use code from the ImageMagick framework.
Just use following code and you got the .tiff image. You have to add ImageIO and MobileCoreServices Frameworks into your project.
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/UTCoreTypes.h>
- (void)viewDidLoad {
[super viewDidLoad];
[self convertImageIntoTIFF];
}
-(void)convertImageIntoTIFF{
UIImage *img = [UIImage imageNamed:#"image.png"];
float compression = 1.0; // Lossless compression if available.
int orientation = 1; // Origin is at top, left.
CFStringRef myKeys[3];
CFTypeRef myValues[3];
CFDictionaryRef myOptions = NULL;
myKeys[0] = kCGImagePropertyOrientation;
myValues[0] = CFNumberCreate(NULL, kCFNumberIntType, &orientation);
myKeys[1] = kCGImagePropertyHasAlpha;
myValues[1] = kCFBooleanTrue;
myKeys[2] = kCGImageDestinationLossyCompressionQuality;
myValues[2] = CFNumberCreate(NULL, kCFNumberFloatType, &compression);
myOptions = CFDictionaryCreate( NULL, (const void **)myKeys, (const void **)myValues, 3,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSLog(#"documentsDirectory %#", documentsDirectory);
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"image.tiff"];
[self writeCGImage:img.CGImage toURL:[NSURL fileURLWithPath:filePath] withType:kUTTypeTIFF andOptions:myOptions];
}
- (void) writeCGImage: (CGImageRef) image toURL: (NSURL*) url withType: (CFStringRef) imageType andOptions: (CFDictionaryRef) options
{
CGImageDestinationRef myImageDest = CGImageDestinationCreateWithURL((CFURLRef)url, imageType, 1, nil);
CGImageDestinationAddImage(myImageDest, image, options);
CGImageDestinationFinalize(myImageDest);
CFRelease(myImageDest);
}
For More details, you can able to download this DemoCode.
Hope, this is what you're looking for. :)
I am new to iPhone programming. I want to read the content of a text file located in a subfolder of the Resource folder.
The Resource folder structure is the following:
Resource
Folder1---->Data.txt
Folder2---->Data.txt
Folder3---->Folder1---->Data.txt
There are multiple files named "Data.txt", so how can I access the files in each folder? I know how to read the text file, but if the Resource structure is similar to the above structure then how can I get the path?
For example, if I want to access the "Data.txt" file from Folder3, how can I get the file path?
Please suggest.
Your "resource folder" is actually the contents of your main bundle, also know as the application bundle. You use pathForResource:ofType: or pathForResource:ofType:inDirectory: to get the full path for a resource.
Loading the contents of a file as a string is done with the stringWithContentsOfFile:encoding:error: method for an autoreleased string of with initWithContentsOfFile:encoding:error: if you want a retained string.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Data"
ofType:#"txt"
inDirectory:#"Folder1"];
if (filePath != nil) {
theContents = [NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:NULL];
// Do stuff to theContents
}
This is almost the same answer as given by Shirkrin previously, but with the slight difference that it works on target. This is because initWithContentsOfFile: is deprecated on Mac OS X, and not available at all iPhone OS.
To continue psychotiks answer a full example would look like this:
NSBundle *thisBundle = [NSBundle bundleForClass:[self class]];
NSString *filePath = nil;
if (filePath = [thisBundle pathForResource:#"Data" ofType:#"txt" inDirectory:#"Folder1"]) {
theContents = [[NSString alloc] initWithContentsOfFile:filePath];
// when completed, it is the developer's responsibility to release theContents
}
Notice that you can use -pathForResource:ofType:inDirectory to access ressources in sub directories.
Shirkrin's answer and PeyloW's answer above were both useful, and I managed to use pathForResource:ofType:inDirectory: to access files with the same name in different folders in my app bundle.
I also found an alternative solution here that suited my requirements slightly better, so I thought I'd share it. In particular, see this link.
For example, say I have the following Folder References (blue icons, Groups are yellow):
Then I can access the image files like this:
NSString * filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"pin_images/1/2.jpg"];
UIImage * image = [UIImage imageWithContentsOfFile:filePath];
As a side note, the pathForResource:ofType:inDirectory: equivalent looks like this:
NSString * filePath = [[NSBundle mainBundle] pathForResource:#"2" ofType:#"jpg" inDirectory:#"pin_images/1/"];
NSBundle* bundle = [NSBundle mainBundle];
NSString* path = [bundle bundlePath];
This gives you the path to your bundle. From there on, you can navigate your folder structure.