OpenCV Integration Example

Note: SwiftCV package requires OpenCV installed in order to compile.


In [ ]:
# Uncomment line below when using Colab (this installs OpenCV4)
# %system SwiftCV/install/install_colab.sh
%install-location $cwd/swift-install
%install '.package(path: "$cwd/SwiftCV")' SwiftCV
%install '.package(path: "$cwd/FastaiNotebook_08_data_block")' FastaiNotebook_08_data_block


Installing packages:
	.package(path: "/home/saeta/fastai_docs/dev_swift/SwiftCV")
		SwiftCV
	.package(path: "/home/saeta/fastai_docs/dev_swift/FastaiNotebook_08_data_block")
		FastaiNotebook_08_data_block
With SwiftPM flags: []
Working in: /tmp/tmpvc9knc87/swift-install
[1/13] Compiling FastaiNotebook_08_data_block 01_matmul.swift
[2/13] Compiling FastaiNotebook_08_data_block 03_minibatch_training.swift
[3/13] Compiling FastaiNotebook_08_data_block 02_fully_connected.swift
[4/13] Compiling FastaiNotebook_08_data_block 05b_early_stopping.swift
[5/13] Compiling FastaiNotebook_08_data_block 05_anneal.swift
[6/13] Compiling FastaiNotebook_08_data_block 06_cuda.swift
[7/13] Compiling FastaiNotebook_08_data_block 02a_why_sqrt5.swift
[8/13] Compiling FastaiNotebook_08_data_block 00_load_data.swift
[9/13] Compiling FastaiNotebook_08_data_block 08_data_block.swift
[10/13] Compiling FastaiNotebook_08_data_block 04_callbacks.swift
[11/13] Compiling FastaiNotebook_08_data_block 01a_fastai_layers.swift
[12/13] Compiling FastaiNotebook_08_data_block 07_batchnorm.swift
[13/14] Merging module FastaiNotebook_08_data_block
[14/15] Compiling jupyterInstalledPackages jupyterInstalledPackages.swift
[15/16] Merging module jupyterInstalledPackages
[16/16] Linking libjupyterInstalledPackages.so
Initializing Swift...
Installation complete!

Imports


In [ ]:
%include "EnableIPythonDisplay.swift"
import Foundation
import SwiftCV
import Path

In [ ]:
import FastaiNotebook_08_data_block

In [ ]:
// display opencv version
print(cvVersion())


4.1.0

Load image


In [ ]:
func readImage(_ path:String)->Mat {
    let cvImg = imread(path)
    return cvtColor(cvImg, nil, ColorConversionCode.COLOR_BGR2RGB)
}

In [ ]:
let path = downloadImagenette(sz:"")
let allNames = fetchFiles(path: path/"train/n03425413", recurse: false, extensions: ["jpeg", "jpg"])
let fNames = Array(allNames[0..<256])
let ns = fNames.map {$0.string}
let imgpath = ns[2]
var cvImg = readImage(imgpath)


Downloading https://s3.amazonaws.com/fast-ai-imageclas/imagenette.tgz...

Timing


In [ ]:
cvImg.size


Out[ ]:
▿ 2 elements
  - 0 : 500
  - 1 : 375

In [ ]:
print(type(of:cvImg.dataPtr))


UnsafeMutablePointer<Int8>

In [ ]:
let ptr = UnsafeRawPointer(cvImg.dataPtr).assumingMemoryBound(to: UInt8.self)

In [ ]:
ptr[2]


Out[ ]:
111

In [ ]:
time(repeating:10) {_ = readImage(imgpath)}


average: 3.2026426999999997 ms,   min: 2.935113 ms,   max: 3.296784 ms

In [ ]:
cvImg.rows


Out[ ]:
500

In [ ]:
import Python
import TensorFlow

In [ ]:
let plt = Python.import("matplotlib.pyplot")
let np = Python.import("numpy")
IPythonDisplay.shell.enable_matplotlib("inline")


Out[ ]:
('inline', 'module://ipykernel.pylab.backend_inline')

In [ ]:
func show_img(_ img: Mat, _ w: Int = 7, _ h: Int = 5) {
    show_img(Tensor<UInt8>(cvMat: img)!, w, h)
}

In [ ]:
show_img(cvImg)



In [ ]:
time(repeating:10) {_ = resize(cvImg, nil, Size(224, 224), 0, 0, InterpolationFlag.INTER_NEAREST)}


average: 0.1347015 ms,   min: 0.08907 ms,   max: 0.22734 ms

In [ ]:
time(repeating:10) {_ = resize(cvImg, nil, Size(224, 224), 0, 0, InterpolationFlag.INTER_LINEAR)}


average: 0.5949585999999999 ms,   min: 0.529687 ms,   max: 0.700341 ms

In [ ]:
time(repeating:10) {_ = resize(cvImg, nil, Size(224, 224), 0, 0, InterpolationFlag.INTER_CUBIC)}


average: 0.5734125999999999 ms,   min: 0.556511 ms,   max: 0.622225 ms

In [ ]:
time(repeating:10) {_ = resize(cvImg, nil, Size(224, 224), 0, 0, InterpolationFlag.INTER_AREA)}


average: 1.5651732000000003 ms,   min: 1.542578 ms,   max: 1.603373 ms

In [ ]:
cvImg = resize(cvImg, nil, Size(224, 224), 0, 0, InterpolationFlag.INTER_CUBIC)

In [ ]:
func readResized(_ fn:String)->Mat {
    return resize(readImage(fn), nil, Size(224, 224), 0, 0, InterpolationFlag.INTER_CUBIC)
}

In [ ]:
var imgs = ns[0..<10].map(readResized)

In [ ]:
time(repeating:10) {_ = readResized(imgpath)}


average: 3.9041422 ms,   min: 3.708008 ms,   max: 4.496613 ms

In [ ]:
public protocol Countable {
    var count:Int {get}
}
extension Mat  :Countable {}
extension Array:Countable {}

public extension Sequence where Element:Countable {
    var totalCount:Int { return map{ $0.count }.reduce(0, +) }
}

In [ ]:
func collateMats(_ imgs:[Mat])->Tensor<Float> {
    let c = imgs.totalCount
    let ptr = UnsafeMutableRawPointer.allocate(byteCount: c, alignment: 1)
    defer {ptr.deallocate()}
    var p = ptr
    for img in imgs {
        p.copyMemory(from: img.dataPtr, byteCount: img.count)
        p += img.count
    }
    let r = UnsafeBufferPointer(start: ptr.bindMemory(to: UInt8.self, capacity: c), count: c)
    cvImg = imgs[0]
    let shape = TensorShape([imgs.count, cvImg.rows, cvImg.cols, cvImg.channels])
    let res = Tensor(shape: shape, scalars: r)
    return Tensor<Float>(res)/255.0
}

In [ ]:
var t = collateMats(imgs)

In [ ]:
t.shape


Out[ ]:
▿ [10, 224, 224, 3]
  ▿ dimensions : 4 elements
    - 0 : 10
    - 1 : 224
    - 2 : 224
    - 3 : 3

In [ ]:
show_img(t[2])



In [ ]:
time(repeating:10) {_ = collateMats(imgs)}


average: 1.9515162 ms,   min: 1.213406 ms,   max: 2.94692 ms

In [ ]:
time { _ = ns.map(readResized) }


average: 1095.155756 ms,   min: 1095.155756 ms,   max: 1095.155756 ms

OpenCV Transformations

Resize


In [ ]:
show_img(
    resize(cvImg, nil, Size(100, 50), 0, 0, InterpolationFlag.INTER_AREA)
)


Zoom / Crop


In [ ]:
let zoomMat = getRotationMatrix2D(Size(cvImg.cols, cvImg.rows / 2), 0, 1)
show_img(
    warpAffine(cvImg, nil, zoomMat, Size(600, 600))
)


Rotate


In [ ]:
let rotMat = getRotationMatrix2D(Size(cvImg.cols / 2, cvImg.rows / 2), 20, 1)
show_img(
    warpAffine(cvImg, nil, rotMat, Size(cvImg.cols, cvImg.rows))
)


Pad


In [ ]:
show_img(
    copyMakeBorder(cvImg, nil, 40, 40, 40, 40, BorderType.BORDER_CONSTANT, RGBA(0, 127, 0, 0))
)


Blur


In [ ]:
show_img(
    GaussianBlur(cvImg, nil, Size(25, 25))
)


Flip


In [ ]:
show_img(
    flip(cvImg, nil, FlipMode.HORIZONTAL)
)


Transpose


In [ ]:
show_img(
    transpose(cvImg, nil)
)



In [ ]: