Dlib image load error, unable to load image - ios

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.

Related

How to use dlib's shape_predictor in Objective-C?

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.

Accessing images from nsbundle

I have a framework which is trying to access xib's and images from a bundle. I am able to access the xib fine but unable to load the images in UIImageView. I even check if the file exists and the console output is yes...
Any idea how to load the image?
Code to load xib in the framework viewcontroller file
self = [super initWithNibName:#"ViewController_iPad" bundle:[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:#"MyBundle" ofType:#"bundle"]]];
Code to load images
- (void) loadImage
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyBundle.bundle/test" ofType:#"png"];
BOOL present = NO;
present = [[NSFileManager defaultManager] fileExistsAtPath:path];
if (present)
{
NSLog(#"MyBundle.bundle/test exists");
}
else
{
NSLog(#"MyBundle.bundle/test does not exists");
}
self.testImageView.image = [UIImage imageNamed:path];
self.testImageView2.image = [UIImage imageWithContentsOfFile:path];
}
MyTestHarnessApp[11671:c07] MyBundle.bundle/test exists
When you use imageNamed: you must pass just a simple filename and the image must exist in the root of the app's resource bundle.
Your image is not in the root of the resource bundle, it is in a subfolder.
Since you have obtained the image's full path in the path variable, you must use the UIImage imageWithContentsOfFile: method:
self.testImageView.image = [UIImage imageWithContentsOfFile:path];
If +[UIImage imageNamed:] isn't resolving the path correctly, you could always use:
self.testImageView.image = [UIImage imageWithContentsOfFile: path];
You can just use the following:
self.testImageView.image = [UIImage imageNamed:#"MyBundle.bundle/test.png"];
But it seems that if you put the XIB in the bundle too, the interface will be relative to the bundle.
self.testImageView.image = [UIImage imageNamed:#"test.png"]
try going step by step.
First get the path to the bundle within your main bundle:
NSString *myBundlePath=[[NSBundle mainBundle] pathForResource:MyBundle ofType:#"bundle"];
Check to see if there is anything in the bundle. This is more for double checking. Once it is working you can choose to omit this code. But it is always a good idea to double check things.
NSBundle *imageBundle=[NSBundle bundleWithPath: myBundlePath];
NSArray *allImageURLs=[imageBundle URLsForResourcesWithExtension:#"png" subdirectory:nil];
NSLog(#"imageURLS: %#",allImageURLS);
Since you already have the bundle path add the image name to the path. Or you can just pull it from the list of urls that you already have in the above code.
NSString *myImagePath=[myBundlePath stringByAppendingPathComponent:#"test.png"];
NSLog(#"myImagePath=%#",myImagePath);
Then, since you have the full path, load the image
UIImage *testImage = [UIImage imageWithContentsOfFile:backgroundImagePath];
Code taken from shipping app.
Good Luck
Tim
If the images are already in the main bundle just use the image name: test.png or simply test
[UIImage imageNamed:#"test.png"];
[UIImage imageNamed:#"test"];

Bundle subdirectory access

I'm try to implement ability to change interface in my program, something like themes. I'm decide to use bundles, so in my case they looks like this:
Theme1.bundle
Theme2.bundle
Every bundle have folders:
Theme1.bundle
graphic
pic1.png
pic2.png
sound
sound1.wav
sound2.wav
So I can get path to any required picture from bundle with this code:
path = [NSString stringWithFormat:#"%#.bundle/graphic/%#", selectedBundle, imageName];
When I get pictures from bundle there is no problem, path looks like this (I check it using breakpoints):
Theme1.bundle/graphic/pic1.png and I create UIImage
image = [UIImage imageNamed:path];
Pictures loaded without any problem.
But when I trying to play sound using AVAudioPlayer, I get path to sound by same way and path looks like this:
Theme1.bundle/sound/sound1.wav, but when I try to create NSData
sound = [NSData dataWithContentsOfFile:path];
it is not initialized.
When I try to keep sounds in main bundle and get it with
path = [[NSBundle mainBundle] pathForResource:#"sound1" ofType:#"wav"];
everything is OK, and path looks like this
/var/mobile/Applications/E8313E88-CE05-44B2-A80C-B05331D8596F/Myapp.app/sound1.wav
I cant understand why this works with pictures but not with sound?
Why I cant get sound from bundle?
Only one thing I can suggest - imageNamed: do some work to find right path to file and dataWithContentsOfFile: does not.
In your code instead of
sound = [NSData dataWithContentsOfFile:path];
Use
NSString * path = [NSString stringWithFormat:#"%#.bundle/sounds/%#", selectedBundle, soundName];
NSString *fullPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:path];
sound = [NSData dataWithContentsOfFile:path];
Explanation:
ImageNamed attaches the path of the application to the image name you specify

Selectively loading low-resolution resources in iOS when #2x-version is also present

I had a lot of trouble trying to force the loading of the low-resolution version of some resources on iOS, when the high-res version (#2x) is also present.
The reason I wanted to do this is simple: My app shows a bunch of full-screen images to the user (320x480 on older devices, 640x960 on Retina devices), and the user can upload some of these to TwitPic. I wanted to unify the uploaded images to 320x480, regardless of the device (for consistency, because that size is fine in a web browser).
I found out that no matter what UIImage method I used, when the high-resolution version of a resource file is present it is loaded (even if you pass the full file path): UIImage will out-smart you. But I found a way to out-smart UIImage:
- (UIImage*) lowResImage{
NSString* path = [[NSBundle mainBundle] pathForResource:_fileName
ofType:#"png"
inDirectory:_resourceSubdirectory];
path = [path stringByReplacingOccurrencesOfString:#"##2x" withString:#""];
NSData* imageData = [[NSData alloc] initWithContentsOfFile:path];
UIImage* image = [[UIImage alloc] initWithData:imageData];
[imageData release];
return [image autorelease];
}
The above code works fine on a 4th generation iPod touch.
Anybody came up with a better approach?
Build your path, open data, and then init the image using data as in the example below.
NSString *dataPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:_fileName];
NSData *data = [[NSData alloc] initWithContentsOfFile:dataPath];
UIImage *image3 = [UIImage imageWithData:data];

iPhone : Get the file path which is within subfolder of Resource folder

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.

Resources