Check if imageView is empty - ios

I have a camera feature in my app and when you take the picture it places that picture into an imageView. I have a button that I've hidden and what I want is for when the image is placed in the imageView for the button to be unhidden.
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var toGoFurther: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
toGoFurther.hidden = true
if (self.imageView.image != nil){
toGoFurther.hidden = false
}
let testObject = PFObject(className: "TestObject")
testObject["foo"] = "bar"
testObject.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
print("Object has been saved.")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func continueNextPage(sender: AnyObject) {
}
#IBAction func takePhoto(sender: AnyObject) {
if !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera){
return
}
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera;
//Create camera overlay
let pickerFrame = CGRectMake(0, UIApplication.sharedApplication().statusBarFrame.size.height, imagePicker.view.bounds.width, imagePicker.view.bounds.height - imagePicker.navigationBar.bounds.size.height - imagePicker.toolbar.bounds.size.height)
let squareFrame = CGRectMake(pickerFrame.width/2 - 400/2, pickerFrame.height/2 - 400/2, 640, 640)
UIGraphicsBeginImageContext(pickerFrame.size)
let context = UIGraphicsGetCurrentContext()
CGContextSaveGState(context)
CGContextAddRect(context, CGContextGetClipBoundingBox(context))
CGContextMoveToPoint(context, squareFrame.origin.x, squareFrame.origin.y)
CGContextAddLineToPoint(context, squareFrame.origin.x + squareFrame.width, squareFrame.origin.y)
CGContextAddLineToPoint(context, squareFrame.origin.x + squareFrame.width, squareFrame.origin.y + squareFrame.size.height)
CGContextAddLineToPoint(context, squareFrame.origin.x, squareFrame.origin.y + squareFrame.size.height)
CGContextAddLineToPoint(context, squareFrame.origin.x, squareFrame.origin.y)
CGContextEOClip(context)
CGContextMoveToPoint(context, pickerFrame.origin.x, pickerFrame.origin.y)
CGContextSetRGBFillColor(context, 0, 0, 0, 1)
CGContextFillRect(context, pickerFrame)
CGContextRestoreGState(context)
let overlayImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
let overlayView = UIImageView(frame: pickerFrame)
overlayView.image = overlayImage
imagePicker.cameraOverlayView = overlayView
self.presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
dismissViewControllerAnimated(true, completion: nil)
}

Try putting this in the viewDidAppear method. That should do it.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
toGoFurther.hidden = self.imageView.image == nil
}

So, you want to unhide your button when image is captured and set on view. You need to do this in your didFinishPickingMediaWithInfo function like this:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject: AnyObject]) {
imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
// dissmiss the image picker controller window
self.dismissViewControllerAnimated(true, completion:^{
toGoFurther.hidden = false
})
}

Related

Why my Object Detection app is not returning anything?

I have a simple app that contains a button, UIImageView, and a label. Once you click on the button, you will be able to take a photo using the camera. Then the model has to predict what is the object in the photo, and finally the label has to display the output (the predicted object).
Everything is working fine and there are no errors, but after I take a picture, the label is not being changed, the model is not returning anything, why is that ?
NOTE: The model is working fine and it has been tested using another app, but I think I am missing something in this code.
Here is my code:
import UIKit
import CoreML
class secondViewController: UIViewController, UINavigationControllerDelegate {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var classifier: UILabel!
var model: VGG16!
let cameraPicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(_ animated: Bool) {
model = VGG16()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func camera(_ sender: Any) {
if !UIImagePickerController.isSourceTypeAvailable(.camera) {
return
}
cameraPicker.delegate = self
cameraPicker.sourceType = .camera
cameraPicker.allowsEditing = false
present(cameraPicker, animated: true)
}
}
extension secondViewController: UIImagePickerControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
// private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
picker.dismiss(animated: true, completion: nil)
let image = info[UIImagePickerController.InfoKey.originalImage]! as! UIImage
picker.dismiss(animated: true)
classifier.text = "Analyzing Image..."
UIGraphicsBeginImageContextWithOptions(CGSize(width: 299, height: 299), true, 2.0)
image.draw(in: CGRect(x: 0, y: 0, width: 299, height: 299))
let newImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
var pixelBuffer : CVPixelBuffer?
let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(newImage.size.width), Int(newImage.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
guard (status == kCVReturnSuccess) else {
return
}
CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: pixelData, width: Int(newImage.size.width), height: Int(newImage.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) //3
context?.translateBy(x: 0, y: newImage.size.height)
context?.scaleBy(x: 1.0, y: -1.0)
UIGraphicsPushContext(context!)
newImage.draw(in: CGRect(x: 0, y: 0, width: newImage.size.width, height: newImage.size.height))
UIGraphicsPopContext()
CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
imageView.image = newImage
// Core ML
guard let prediction = try? model.prediction(image: pixelBuffer!) else {
return
}
classifier.text = "I think this is a \(prediction.classLabel)."
}
}
You need to hold a strong reference to
let cameraPicker = UIImagePickerController()
override func viewDidLoad() {
by making it an instance variable for the delegate methods to be called

How to add UIImage to a Scene in AR Kit

I have AR session which adds SCNText and 3D Objects as well. And now, I want to add UIImage from Image Picker and don't know how to do this. Is there any solutions?
SOLUTION
func insertImage(image: UIImage, width: CGFloat = 0.3, height: CGFloat = 0.3) -> SCNNode {
let plane = SCNPlane(width: width, height: height)
plane.firstMaterial!.diffuse.contents = image
let node = SCNNode(geometry: plane)
node.constraints = [SCNBillboardConstraint()]
return node
}
let image = insertImage(image: addedImage)
node.addChildNode(image)
As I am sure you are aware an SCNGeometry has a materials property which is simply:
A container for the color or texture of one of a material’s visual
properties.
As such you could render a UIImage onto an SCNGeometry using for example the diffuse property.
Here is a fully working and tested example. Which loads a UIImagePickerController after 5 seconds, and then creates an SCNNode with an SCNPlane Geometry which has is contents set to the selected UIImage.
The code is fully commented so it should be easy enough to understand:
//-------------------------------------
//MARK: UIImagePickerControllerDelegate
//-------------------------------------
extension ViewController: UIImagePickerControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//1. Check We Have A Valid Image
if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
//2. We Havent Created Our PlaneNode So Create It
if planeNode == nil{
//d. Dismiss The Picker
picker.dismiss(animated: true) {
//a. Create An SCNPlane Geometry
let planeGeometry = SCNPlane(width: 0.5, height: 0.5)
//b. Set's It's Contents To The Picked Image
planeGeometry.firstMaterial?.diffuse.contents = self.correctlyOrientated(selectedImage)
//c. Set The Geometry & Add It To The Scene
self.planeNode = SCNNode()
self.planeNode?.geometry = planeGeometry
self.augmentedRealityView.scene.rootNode.addChildNode(self.planeNode!)
self.planeNode?.position = SCNVector3(0, 0, -1.5)
}
}
}
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true, completion: nil) }
}
class ViewController: UIViewController, UINavigationControllerDelegate {
//1. Create A Reference To Our ARSCNView In Our Storyboard Which Displays The Camera Feed
#IBOutlet weak var augmentedRealityView: ARSCNView!
//2. Create Our ARWorld Tracking Configuration & Session
let configuration = ARWorldTrackingConfiguration()
let augmentedRealitySession = ARSession()
//3. Create A Reference To Our PlaneNode
var planeNode: SCNNode?
var planeGeomeryImage: UIImage?
//---------------
//MARK: LifeCycle
//---------------
override func viewDidLoad() {
super.viewDidLoad()
//1. Setup The Session
setupARSession()
//2. Show The UIImagePicker After 4 Seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
self.selectPhotoFromGallery()
}
}
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
//-------------
//MARK: ARSetup
//-------------
func setupARSession(){
//1. Run Our Session
augmentedRealityView.session = augmentedRealitySession
augmentedRealitySession.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
//---------------------
//MARK: Image Selection
//---------------------
/// Loads The UIImagePicker & Allows Us To Select An Image
func selectPhotoFromGallery(){
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
}
/// Correctly Orientates A UIImage
///
/// - Parameter image: UIImage
/// - Returns: UIImage?
func correctlyOrientated(_ image: UIImage) -> UIImage {
if (image.imageOrientation == .up) { return image }
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
let rect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
image.draw(in: rect)
let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return normalizedImage
}
}
Don't forget to add the NSPhotoLibraryUsageDescription to your info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>For ARkit</string>
This should be more than enough to get you started...

Image Selected From Image Picker Not Displaying

I'm kind of lost. My Image Picker is working but the image is not displaying in my Image View. I have looked over my code and various solutions and it still is not working. I have set the delegate to self and double checked my methods and it is still not showing the image where it is supposed to.
import UIKit
class AlterProfileViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
view?.backgroundColor = UIColor.white
navigationItem.title = "Profile Settings"
view.addSubview(selectProfileImage)
///Constraints for all views will go here
_ = selectProfileImage.anchor(view.centerYAnchor, left: view.leftAnchor, bottom: nil, right: nil, topConstant: -275, leftConstant: 135, bottomConstant: 0, rightConstant: 0, widthConstant: 100, heightConstant: 100)
// selectProfileImage.layer.cornerRadius = selectProfileImage.frame.size.width/2
///////////////////////////////////////////////
// Do any additional setup after loading the view.
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
selectProfileImage.layer.cornerRadius = selectProfileImage.frame.size.width / 2;
selectProfileImage.layer.masksToBounds = true
}
//Where all buttons and labels will be added
//will just be a nice looking image view to be next to the profile settings button
lazy var selectProfileImage: UIImageView = {
let selectPicture = UIImageView()
// self.selectProfileImage.layer.cornerRadius = self.selectProfileImage.frame.size.width / 2;
selectPicture.image = UIImage(named: "Paris")
// selectPicture.layer.cornerRadius = selectPicture.frame.size.width / 2;
selectPicture.clipsToBounds = true
selectPicture.translatesAutoresizingMaskIntoConstraints = false
selectPicture.layer.cornerRadius = selectPicture.frame.size.width/2
selectPicture.contentMode = .scaleAspectFill
selectPicture.isUserInteractionEnabled = true
selectPicture.layer.shouldRasterize = true
// will allow you to add a target to an image click
selectPicture.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView)))
selectPicture.layer.masksToBounds = true
return selectPicture
}()
func handleSelectProfileImageView() {
print("123")
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
// will dispaly info of image selected
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("info")
var selectedImageFromPicker: UIImage?
if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage{
print((editedImage as AnyObject).size)
selectedImageFromPicker = editedImage
}else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage{
print((originalImage as AnyObject).size)
selectedImageFromPicker = originalImage
}
if let selectedImage = selectedImageFromPicker {
selectProfileImage.image = selectedImage
}
dismiss(animated: true, completion: nil)
}
// will handle the picker being closed/canceled
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("picker canceled")
dismiss(animated: true, completion: nil)
}
///////////////////////////////////////////////////////////////////////////////////
}

Variable turns nill when a view changes

My ViewController - I am just selecting an image and then updating imageView. Still, whenever I am leaving the view, the ImageView is back to "face-unknown", because newImage is nill.
Why doesn't the variable newImage remember the image after the view changes?
var newImage: UIImage!
#IBOutlet weak var imageView: UIImageView!
var imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
if((newImage == nil)){
imageView.image = UIImage(named:"face-unknown")!
}else{
imageView.image = newImage
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let possibleImage = info["UIImagePickerControllerEditedImage"] as? UIImage {
imageView.image = resizeImage(possibleImage,newWidth: 150)
newImage = resizeImage(possibleImage,newWidth: 150)
} else if let possibleImage = info["UIImagePickerControllerOriginalImage"] as? UIImage {
imageView.image = resizeImage(possibleImage,newWidth: 150)
newImage = resizeImage(possibleImage,newWidth: 150)
} else {
return
}
Your imageView is back to "face-unknown" because the viewDidLoad() method is called only once. Not because your UIImage is nil. Instead try to update your UIImageView in the viewWillAppear() method, it should works

ImageView in a ScrollView to zoom, crop and save swift

I am trying to let the user make a profile picture on my app, but I have been running into problems I can seem to solve.
I have added a uiscrollview on my viewcontroller. Next I added a UIimageview into the uiscrollview, both are the same width and height.
The first thing I was trying to solve is I wanted the picture the user inputs to fill the uiimageview by the shortest side. So if the image had a width of 500 and height of 1000, I want the width to fill the image view with the extra height off the top and bottom waiting for the user to scroll.
I am also having trouble panning images. It seems like I can't pan an image until I pinch zoom on the image. Saying this I also think my full image is not being displayed which may be causing some problems, I'm not sure why.
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIScrollViewDelegate {
#IBOutlet var scrollView: UIScrollView!
#IBOutlet var imageViewPicture: UIImageView!
#IBOutlet var addPicture: UIButton!
let image = UIImagePickerController()
#IBAction func addPicture(sender: AnyObject) {
self.presentViewController(image, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
self.dismissViewControllerAnimated(true, completion: nil)
imageViewPicture.image = image
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.orangeColor()
self.scrollView.backgroundColor = UIColor.blueColor()
self.scrollView.delegate = self
//setting the min and max amount of zoom on the picture
self.scrollView.minimumZoomScale = 1.0
self.scrollView.maximumZoomScale = 4.0
self.scrollView.bouncesZoom = false
self.scrollView.bounces = false
self.scrollView.alwaysBounceVertical = false
self.scrollView.alwaysBounceHorizontal = false
self.scrollView.scrollEnabled = true
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
image.allowsEditing = false
scrollView.layer.cornerRadius = (imageViewPicture.frame.size.width) / 2
scrollView.layer.masksToBounds = true
//gets rid of the indicator that shows where you are when scrolling
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
imageViewPicture.userInteractionEnabled = true
let doubleTap = UITapGestureRecognizer(target: self, action: "doubleTapped")
doubleTap.numberOfTapsRequired = 2
imageViewPicture.addGestureRecognizer(doubleTap)
}
func doubleTapped() {
if scrollView.zoomScale > 1.0 {
scrollView.zoomScale = 1.0
} else {
scrollView.zoomScale = 2.0
}
}
func cropAndSave() {
UIGraphicsBeginImageContextWithOptions(scrollView.bounds.size, true, UIScreen.mainScreen().scale)
let offset = scrollView.contentOffset
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -offset.x, -offset.y)
scrollView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return self.imageViewPicture
}
Background:
UIScrollview (with user interaction enabled and multiple touch enabled)added in the storyboard and set the height width ration 1 - just to make it a square. Panning and zooming is possible with this. I did not do additional set up like corner radius etc. I did this recently - thought it may help you.
class ViewController: UIViewController, UIImagePickerControllerDelegate,UINavigationControllerDelegate ,UIScrollViewDelegate{
var imgview: UIImageView!
var imagepicked:UIImage!
#IBOutlet weak var scrollViewSquare: UIScrollView!
let picker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
picker.delegate = self
scrollViewSquare.delegate = self
//ImageViewInit()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func ImageViewInit(){
imgview = UIImageView()
imgview.frame = CGRectMake(0, 0, imagepicked.size.width, imagepicked.size.height)
imgview.image = imagepicked
imgview.contentMode = .ScaleAspectFit
imgview.backgroundColor = UIColor.lightGrayColor()
scrollViewSquare.maximumZoomScale=4;
scrollViewSquare.minimumZoomScale=0.02;
scrollViewSquare.bounces=true;
scrollViewSquare.bouncesZoom=true;
scrollViewSquare.contentMode = .ScaleAspectFit
scrollViewSquare.contentSize = imagepicked.size
scrollViewSquare.autoresizingMask = UIViewAutoresizing.FlexibleWidth
scrollViewSquare.addSubview(imgview)
setZoomScale()
}
var minZoomScale:CGFloat!
func setZoomScale(){
let imageViewSize = imgview.bounds.size
let scrollViewSize = scrollViewSquare.bounds.size
let widthScale = scrollViewSize.width / imageViewSize.width
let heightScale = scrollViewSize.height / imageViewSize.height
minZoomScale = max(widthScale, heightScale)
scrollViewSquare.minimumZoomScale = minZoomScale
scrollViewSquare.zoomScale = minZoomScale
print("height nd width scale \(widthScale) & \(heightScale) Min zoom scale \(minZoomScale)")
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imgview
}
func imagePickerController(
picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : AnyObject])
{
imagepicked = (info[UIImagePickerControllerOriginalImage] as? UIImage)!
print("Image (h,w) = (\(imagepicked.size.height) , \(imagepicked.size.width))")
ImageViewInit()
dismissViewControllerAnimated(false, completion: nil)
}
#IBAction func Pick(sender: AnyObject) {
picker.allowsEditing = false
picker.sourceType = .PhotoLibrary
presentViewController(picker, animated: true, completion: nil)
}
}

Resources