essay on programming languages, computer science, information techonlogies and all.

Wednesday, June 13, 2018

C++ thread

std::thread with static function


#include 

void called_from_static_fn( const std::string& arg )
{
  // ...
}

std::thread t1(called_from_static_fn, "static");
// ...
t1.join();

std::thread with member fn


class Foo
{
public:
	void Bar( const string& arg)
	{
		// ...
	}
};

Foo foo;
thread t1(&Foo::Bar, &foo, "member");
// ...
t1.join();

std::thread with lambda


int ret = 0;
thread t( [ &ret ](int m, int n) { ret = m + n; }, 2, 4 );
t.join();

std::thread in array


static int twice(int m) { return 2 * m; }

vector< thread > threads;
for (int i = 0; i < 10; ++i)
{
  threads.push_back( thread(twice, i));
}

for (auto& t : threads)
{
  t.join();
}

catch exception in a thread


static int DoNotTryAtHome()
{
  throw exception("I said NO");
}

thread t1(DoNotTryAtHomeNoThrow);
t1.join();

use mutex on shared variable


class Foo 
{
	int m_Bar = 0;
	mutex m_LockBar;
public:
	void AddBarSafe(int add)
	{
		lock_guard< mutex > guard(m_LockBar);
		int temp = m_Bar;
		this_thread::sleep_for(chrono::milliseconds(10));
		m_Bar = temp + add;
	}
};

{
	Foo foo;
	vector ts;
	ts.emplace_back(thread{ &Foo::AddBarSafe, &foo, 2 });
	ts.emplace_back(thread{ &Foo::AddBarSafe, &foo, 3 });
	ts.emplace_back(thread{ &Foo::AddBarSafe, &foo, 4 });

	for (auto& t : ts) {  t.join(); }
}

std::thread on class operator()


struct funcCount
{
	int &i;
	funcCount(int& i_) : i(i_) {}
	void operator()()
	{
		for (unsigned j = 0; j < 1000; ++j)
		{
			++i;
			this_thread::sleep_for(chrono::milliseconds(1));
		}
	}
};

{
	int some_local_state = 0;
	funcCount my_func(some_local_state);
	std::thread my_thread(my_func);
	// my_thread.detach();				// undefined behaviour
	my_thread.join();
}

thread_guard


class thread_guard
{
	std::thread& t;
public:
	explicit thread_guard(std::thread& t_) : t(t_) {}
	~thread_guard() 
	{ 
		if (t.joinable()) t.join(); 
	}

	thread_guard(thread_guard const&) = delete;
	thread_guard operator = (thread_guard const &) = delete;
};

void do_something_stupid()
{
	for (int i = 1; i < 10; ++i)
	{
		if (i % 5 == 0)
		{
			throw std::exception("ooops");
		}
	}
}

{
	int some_local_state = 0;
	try
	{
		funcCount my_func(some_local_state);
		std::thread t(my_func);
		thread_guard g(t);
		do_something_stupid();
	}
	catch (...)
	{
	}
}

move around thread


{
	std::thread t1(called_from_static_fn, "static");
	std::thread t2 = std::move(t1);
	t1 = std::thread(&TestMultiThread::called_from_member_fn, this, "static");
	std::thread t3;
	t3 = std::move(t2);
	// t1 = std::move(t3);   //  terminate

	t1.join();
	t3.join();
}

async


{
	future result(async(called_from_static_fn, "static"));
	result.get();
}

{
	Foo foo;
	future result(async(&Foo::Bar, &foo, "member"));
	result.get();
}

{
	future result(async([](int m, int n) { return m + n; }, 2, 4));
	int ret = result.get();
}

{
	vector< future< int > > futures;
	for (int i = 0; i < 10; ++i)
	{
		futures.push_back(async(twice, i));
	}

	for (auto& e : futures)
	{
		cout << e.get() << endl;
	}
}

async will throw exception at convenient time


{
	future result(async(DoNotTryAtHome));
		
	try
	{
		int ret = result.get();
	}
	catch (exception& ex)
	{
		printf("exception caught : %s", ex.what());
	}
}

wait for future


{
	future f = async( [](){ cout << "bar" << endl; } );
		
	if (f.wait_for(chrono::milliseconds(0)) == future_status::deferred)
	{
		cout << "foo and wait for bar" << endl;
		f.get();
	}
	else
	{
		while (f.wait_for(chrono::milliseconds(10)) != future_status::ready)
		{
			cout << "foo waiting ... " << endl;
		}

		cout << "foo" << endl;
	}
}

condition_variable


{
	mutex m_LockReadyProcess;
	condition_variable m_Condition;
	string m_Log;
	bool m_Ready = false;
	bool m_Processed = false;
}

void worker_thread()
{
	unique_lock lock(m_LockReadyProcess);
	m_Condition.wait(lock, [=]{return m_Ready; });

	cout << "Worker thread is processing data\n";
	m_Log += " after processing";

	m_Processed = true;
	cout << "Worker thread signals data processing completed\n";

	lock.unlock();
	m_Condition.notify_one();
}

{
	thread worker( &TestMultiThread::worker_thread, this);

	m_Log = "Example data";

	{
		lock_guard guard(m_LockReadyProcess);
		m_Ready = true;
		cout << "main() signals data ready for processing\n";
	}
	m_Condition.notify_one();

	{
		unique_lock lock(m_LockReadyProcess);
		m_Condition.wait(lock, [=]{return m_Processed; });
	}
	cout << "Back in main(), data = " << m_Log << '\n';

	worker.join();
}

Wednesday, June 6, 2018

Cryptography tutorial using Poco

Poco has crypto module and here is a tutorial of cryptography using Poco. Symmetric encryption is encrypt and decrypt using a key known by two player. Simple but hard to make key to be safe.

#include "Poco/Crypto/Cipher.h"
#include "Poco/Crypto/CipherKey.h"
#include "Poco/Crypto/CipherFactory.h"

auto& factory = CipherFactory::defaultFactory();
string transmission;

{
  Cipher* alice = factory.createCipher( CipherKey( 
    "aes-256-ecb", "open sesame"));
  transmission = alice->encryptString( 
    "Tall tree, Spy-glass shoulder, ... Skeleton Island ESE and by E");
}

{
  Cipher* bob = factory.createCipher( CipherKey( 
    "aes-256-ecb", "open sesame"));
  string decrypted = bob->decryptString(transmission);
  assert(decrypted == 
    "Tall tree, Spy-glass shoulder, ... Skeleton Island ESE and by E");
}
To remove this unsafe key, asymmetric encryption can be used. To do it, first priavate and public key should be generated. OpenSSL can be used like below.


>openssl.exe genrsa -des3 -out private_bob.pem 2048
Generating RSA private key, 2048 bit long modulus
...................+++
.................................................................+++
unable to write 'random state'
e is 65537 (0x10001)
Enter pass phrase for private_bob.pem:
Verifying - Enter pass phrase for private_bob.pem:


>openssl.exe rsa -in private_bob.pem -outform PEM -pubout -out public_bob.pem
Enter pass phrase for private_bob.pem:
writing RSA key

Then Alice can encode message using Bob's public key. Then only Bob can decode it using his private key.

#include "Poco/Crypto/RSAKey.h"
#include "Poco/Crypto/RSADigestEngine.h“

auto& factory = CipherFactory::defaultFactory();
string transmission;

{
  Cipher* alice = factory.createCipher(RSAKey( "public_bob.pem"));
  transmission = alice->encryptString(
    "Tall tree, Spy-glass shoulder, ... Skeleton Island ESE and by E");
}

{
  Cipher* bob = factory.createCipher(RSAKey( "", "private_bob.pem", "bobbob"));
  string decrypted = bob->decryptString(transmission);
  assert(decrypted == "Tall tree, Spy-glass shoulder, ... Skeleton Island ESE and by E");
}
The assymetric encryption can be extended to make contract between two players which is called digital signature.
Here, Alice can verify Bob's digital signature with the contract he promised.

// Poco::DigestEngine::Digest is std::vector 
tuple transmission;

{
  string contract = 
    "Alice will give Bob $100 and Bob will give Alice two magic mushrooms";
  RSADigestEngine bob(RSAKey("", "private_bob.pem", "bobbob"));
  bob.update(contract);
  transmission = make_tuple(contract, bob.signature());
}

{
  RSADigestEngine alice(RSAKey("public_bob.pem"));
  alice.update(get<0>(transmission));
  bool isValid = alice.verify(get<1>(transmission));
  assert(isValid == true);
}

Imagine, Alice get greedy and forged the contract, then Bob's signature doesn't work anymore.

// Poco::DigestEngine::Digest is std::vector 
tuple transmission;

{
  string contract = 
    "Alice will give Bob $100 and Bob will give Alice two magic mushrooms";
  RSADigestEngine bob(RSAKey("", "private_bob.pem", "bobbob"));
  bob.update(contract);
  transmission = make_tuple(contract, bob.signature());
}

{
  RSADigestEngine alice(RSAKey("public_bob.pem"));
  alice.update(
    "Alice will give Bob $100 and Bob will give Alice three magic mushrooms");
  bool isValid = alice.verify(get<1>(transmission));
  assert(isValid == false);
}
This digital signature can be extended further to digital coin. First chained transaction should be established. Here is a diagram from Satoshi Nakamoto's paper which shows the concept.

Here, Queen generate coin and give it to Alice; Queen use Alice's public key to generate transaction hash and sign the hash using majesty private key.

struct Transaction
{
  string Hash;
  vector Signature;
};

Transaction queenToAlice;
{
  // Queen
  RSAKey alicePublic("public_alice.pem");
  stringstream alicePublickey;
  alicePublic.save(&alicePublickey);

  Crypto::DigestEngine hasher("SHA256");
  hasher.update("Queen's own right to create coin");
  hasher.update(alicePublickey.str());
  string hash = Crypto::DigestEngine::digestToHex(
  hasher.digest());

  RSADigestEngine queen(RSAKey("", "private_queen.pem", "queenqueen"));
  queen.update(hash);

  queenToAlice = Transaction{ hash, queen.signature() };
}
Now, Alice can verify Queen's benevolence using Queen's public key.

{
  // Alice
  RSADigestEngine alice(RSAKey("public_queen.pem"));
  alice.update( queenToAlice.Hash );
  assert( true == alice.verify(queenToAlice.Signature));
}
Then Alice send the coin to Bob; Update the transaction 's hash with Bob's public key and sign it with Alice's private key.

Transaction aliceToBob;
{
  // Alice
  RSAKey bobPublic("public_bob.pem");
  stringstream bobPublickey;
  bobPublic.save(&bobPublickey);

  Crypto::DigestEngine hasher("SHA256");
  hasher.update(queenToAlice.Hash);
  hasher.update(queenToAlice.Signature.data(), 
  queenToAlice.Signature.size());
  hasher.update(bobPublickey.str());
  string hash = Crypto::DigestEngine::digestToHex(
  hasher.digest());

  RSADigestEngine alice(RSAKey("", 
    "private_alice.pem", "alicealice"));
  alice.update(hash);

  aliceToBob = Transaction{ hash, alice.signature() };
}
And Bob can verfiy Alice's coin given to himself.

{
  // Bob
  RSADigestEngine bob(RSAKey("public_alice.pem"));
  bob.update(aliceToBob.Hash);
  assert(true == bob.verify(aliceToBob.Signature));
}
The genuine idea of Bitcoin is BlockChain which verify the transaction in decentralized way. Here is another excerpt from the paper.
It says there should be proof-of-work ; which is basically finding a additional string - nounce - that make hash to start with number of '0' characters. Finding nounce is hard but verifying it is easy. Here is how to verify nounce.

struct Transaction {  string Hash, Signature; };

struct Block {
  string PrevHash, Nounce;
  vector Transactions;
};

Block t0 = {
  "Hello, world!", "4250",  { Transaction{ "", "" } }
};


// verfiy t0 block's transactions and proof-of-work
hasher.update(t0.PrevHash);
for (auto tx : t0.Transactions) {
  hasher.update(tx.Hash); hasher.update(tx.Signature);
}
hasher.update(t0.Nounce);

t1.PrevHash = Crypto::DigestEngine::digestToHex(hasher.digest());
assert(t1.PrevHash.substr(0, 4) == "0000");
Here is a way to finding nounce by brute-force.

// gather transactions
t1.Transactions = { 
  Transaction{ "ab", "cd" }, 
  Transaction{ "12", "34" }, 
  Transaction{ "56", "78" } };

// race for the nounce
for (int nounce = 0;; ++nounce)
{
  hasher.reset();
  hasher.update(t1.PrevHash);
  for (auto tx : t1.Transactions) {
    hasher.update(tx.Hash); hasher.update(tx.Signature);
  }
  hasher.update(to_string(nounce));

  string hash = Crypto::DigestEngine::digestToHex(hasher.digest());
  if (hash.substr(0, 4) == "0000") {
    t1.Nounce = to_string(nounce);
    break;
  }
}

// broadcast t1 block to world 

Saturday, May 19, 2018

Using .NET assembly in C++ via COM Interoperability

.NET assembly can be exposed as COM and C++ import it using ATL COM interface. Data should be marshalled to / from .NET Here is a IFoo declared using C# and its usage in C++ using ATL COM.

namespace MyCompany.Lib
{
    [ComVisible(true)]
    [Guid("71D1B3CD-3CE8-46B8-BF36-329543717F03")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IFoo
    {
        int Bar(int arg);
    }

    [ComVisible(true)]
    [Guid("6F1C4CFC-4BBF-46A1-A9DD-98A4D83691D1")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("MyCompany.Lib.Foo")]
    public class Foo : IFoo
    {
        public int Bar(int arg)
        {
            return 42 + arg;
        }
    }
}

#include < atlbase.h >
#include < atlcom.h >
#include < atlstr.h >

#import "...\MyCompany.Lib.tlb" named_guids

{
  using namespace MyCompany_Lib;
  IFooPtr foo(__uuidof(Foo));
  long ret = foo->Bar(42);
  assert(ret == 84);
}
In C++ project, there will be tlb which has GUID of IFoo and Foo class.

namespace MyCompany.Lib {

struct __declspec(uuid("71d1b3cd-3ce8-46b8-bf36-329543717f03")) IFoo;

_COM_SMARTPTR_TYPEDEF(IFoo, __uuidof(IFoo));

struct __declspec(uuid("71d1b3cd-3ce8-46b8-bf36-329543717f03"))
IFoo : IDispatch
{
    long Bar (long arg );

    virtual HRESULT __stdcall raw_Bar ( long arg, long * pRetVal ) = 0;
}

struct __declspec(uuid("6f1c4cfc-4bbf-46a1-a9dd-98a4d83691d1")) Foo;

#include "...\MyCompany.Lib.tli"

And tli file that has helper method that deals with COM boundary - HRESULT and exception handling.

inline long IFoo::Bar ( long arg ) {
    long _result = 0;
    HRESULT _hr = raw_Bar(arg, &_result);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _result;
}
Note that C# project should register the .NET assembly. Or tlbimp.exe should be used. Also before deloy the .NET assembly, it should be signed so that it can be registerd and exposed to COM framework of Windows.
At C#, there can be numer of different ComInterfaceType which are mapped to different interface.

...
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFoo
{
...

...
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IFoo
{
...

...
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IFoo
...


class IUnknown {
  virtual HRESULT QueryInterface( REFIID riid, __RPC_FAR *ppvObject) = 0;
  virtual ULONG AddRef( void) = 0;
  virtual ULONG Release( void) = 0;
}

class IDispatch : public IUnknown {
  virtual HRESULT GetTypeInfoCount(UINT *pctinfo) = 0;        
  virtual HRESULT GetTypeInfo( ...) = 0;
  virtual HRESULT GetIDsOfNames( ... ) = 0;
  virtual HRESULT Invoke( ... ) = 0;
} 


// tlb
IFoo : IUnknown
{

IFoo : IDispatch
{

IFoo : IDispatch
{

There is ClassInterfaceType. 'AutoDual' add interface method of C# Object class.

[ClassInterface(ClassInterfaceType.None)]
public class Foo : IFoo
{
...


[ClassInterface(ClassInterfaceType.AutoDual)]
public class ProgressBase
{


// tlb

struct __declspec(uuid("6f1c4cfc-4bbf-46a1-a9dd-98a4d83691d1"))
Foo;



struct __declspec(uuid("97754ee6-048b-3d1d-a477-deb25d4bc983"))
_ProgressBase : IDispatch
{
    __declspec(property(get=GetToString))
    _bstr_t ToString;

    _bstr_t GetToString ( );
    VARIANT_BOOL Equals ( const _variant_t & obj );
    long GetHashCode ( );
    _TypePtr GetType ( );

...

Property of C# can be access using Getxxx(), Putxxx(). Or it can be directly accessed like member variable.


    public interface IFoo
    {
        int Koo { get; set; }
    }

    public class Foo : IFoo
    {
        public int Koo
        {
            get;
            set;
        }
    }


IFooPtr foo(__uuidof(Foo));

foo->PutKoo(42);
ret = foo->GetKoo();
assert(ret == 42);

foo->Koo = 11;
assert(foo->Koo == 11);
ret = foo->GetKoo();
assert(ret == 11);
C# Exception will cause HRESULT to be retured as FAIL and will be rethrown as com_error at tli code.

    public class Foo : IFoo
    {
        public int Bar(int arg)
        {
            if( arg != 42 )
            {
                throw new ArgumentException(
                   "Only 42 allowed");
            }

            return 42 + arg;
        }
    }

IFooPtr foo(__uuidof(Foo));

try
{
  ret = foo->Bar(43);
}
catch (_com_error& ex)
{
  cout << ex.Source() << " ," << ex.Description() << endl;
}


> MyCompany.Lib , Only 42 allowed
ProgId can be declared and used instead of GUID to locate specific COM object.

namespace MyCompany.Lib
{
    [ComVisible(true)]
    [Guid("71D1B3CD-3CE8-46B8-BF36-329543717F03")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IFoo
    {
        int Bar(int arg);
    }

    [ComVisible(true)]
    [Guid("6F1C4CFC-4BBF-46A1-A9DD-98A4D83691D1")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("MyCompany.Lib.Foo")]
    public class Foo : IFoo
    {
        public int Bar(int arg)
        {
            return 42 + arg;
        }
    }
}

IFooPtr foo = IFooPtr(L"MyCompany.Lib.Foo");
ret = foo->Bar(42);
assert(ret == 84);

Copy data between C# and C++, marshalling should handled. In here, C++ call CreateImage with image pointer. Then C# marshall the image data to .NET space and then wrap it up to another interface and return it to C++ like a handle.

[ComVisible(true)]
[Guid("6A56D671-70DA-481A-AA9C-080B97D016D6")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IImage
{
    byte[] Data { get; }
    int Width { get; }
    int Height { get; }
    byte GetPixel(int x, int y);
}

internal class ImageBase : IImage
{
    public byte[] Data { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public byte GetPixel(int x, int y)
    {
        return Data[y * Width + x];
    }
}

[ComVisible(true)]
[Guid("9B5F50F0-66AB-40E1-8150-3E3688D297A7")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IImageFactory
{
    IImage CreateImage(
      IntPtr data, int width, int height);
}


[ComVisible(true)]
[Guid("9B5F50F0-66AB-40E1-8150-3E3688D297A7")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IImageFactory
{
    IImage CreateImage(
      IntPtr data, int width, int height);
}

[ComVisible(true)]
[Guid("8F5BB630-4736-4099-8F93-B23AFDC2AF2D")]
[ClassInterface(ClassInterfaceType.None)]
public class ImageFactory : IImageFactory
{
     public IImage CreateImage(
        IntPtr data, int width, int height )
     {
        int size = width * height;
        byte[] managedData = new byte[size];
        Marshal.Copy(data, managedData, 0, size);
        return new ImageBase { 
           Data = managedData, 
           Width = width, 
           Height = height 
        };
    }
}


vector m(320 * 240, 0);
m[24 + 42 * 320] = 0x42;

IImageFactoryPtr fab(__uuidof(ImageFactory));
IImagePtr image = fab->CreateImage_2( 
   (LONG)m.data(), 320, 240);

uint8_t pixelValue = image->GetPixel(24, 42);
assert(pixelValue == 0x42);
C# enum go through barrier by tli which declare C++ enum - weak type - with a unique underscored name.

[ComVisible(true)]
[Guid("DD6EF614-CA16-43C1-9FD8-CBA386FD43C1")]
public enum AlgorithmTarget
{
    General = 0,
    Scratch = 1,
    Brightness = 2,
    Focus = 3,
}

[ComVisible(true)]
[Guid("FDE54767-12B4-4084-8868-F0033CE9ABD5")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAlgorithm
{
    AlgorithmTarget Target { get; }
}

[ComVisible(true)]
[Guid("24A6E633-5911-4948-866A-CAF357D22BE2")]
[ClassInterface(ClassInterfaceType.None)]
public class ThresholdAlgorithm : IAlgorithm
{
    public AlgorithmTarget Target {
        get {
            return AlgorithmTarget.Brightness;
        }
    }
}


// tlb
enum __declspec(uuid("dd6ef614-ca16-43c1-9fd8-cba386fd43c1"))
AlgorithmTarget
{
    AlgorithmTarget_General = 0,
    AlgorithmTarget_Scratch = 1,
    AlgorithmTarget_Brightness = 2,
    AlgorithmTarget_Focus = 3
};


// cpp
IAlgorithmPtr algo(__uuidof(ThresholdAlgorithm));
assert(algo->Target == AlgorithmTarget_Brightness);
C# Struct maps to C++ struct by tlb. Note 'int' is changed to 'long'.

[ComVisible(true)]
[Guid("2672A17B-0D1A-4C8C-9922-D7E78A746D8E")]
public struct Defect
{
    public int X;
    public int Y;
    public int Area;
}

...
public interface IAlgorithm
{
    int GetDefectCount();
    void FillDefect(int index, ref Defect d);
    Defect GetDefect(int index);
}

...
public class ThresholdAlgorithm : IAlgorithm
{
    public int GetDefectCount() { return 2; }
    public Defect GetDefect(int index)
    {
        return new Defect { X = 3, Y = 2, Area = 1 };
    }
    public void FillDefect(int index, ref Defect d)
    {
        d.X = 1;
        d.Y = 2;
        d.Area = 3;
    }
}


// tlb
#pragma pack(push, 4)
struct __declspec
(uuid("2672a17b-0d1a-4c8c-9922-d7e78a746d8e"))
Defect
{
    long x;
    long y;
    long Area;
};



IAlgorithmPtr algo(__uuidof(ThresholdAlgorithm));
assert(algo->GetDefectCount() == 2);

Defect d = algo->GetDefect(0);
assert(d.x == 3);
assert(d.y == 2);
assert(d.Area == 1);

algo->FillDefect(0, &d);
assert(d.x == 1);
assert(d.y == 2);
assert(d.Area == 3);
IEnumerable is mapped to IEnumVARIANTPtr. C++ part can be bit strong to swallow though.

...
public interface IAlgorithm
{
    void SetImage(int index, IImage image);

    [ComVisible(false)]
    IEnumerable Images { get; }

    System.Collections.IEnumerator GetImageEnumerator();
}

...
public class ThresholdAlgorithm : IAlgorithm
{
    IDictionary IndexedImages = 
       new Dictionary();

    public void SetImage(int index, IImage image)
    {
        if( IndexedImages.ContainsKey(index)) {
            IndexedImages[index] = image;
        } else {
            IndexedImages.Add(index, image);
        }
    }

    public IEnumerable Images { 
        get { return IndexedImages.Values; }
    }

    public IEnumerator GetImageEnumerator() {
        return IndexedImages.Values.GetEnumerator();
    }


IAlgorithmPtr algo(__uuidof(ThresholdAlgorithm));

IImageFactoryPtr fab(__uuidof(ImageFactory));
algo->SetImage(0, fab->CreateImage_3(320, 240, 8, 42));
algo->SetImage(1, fab->CreateImage_3(64, 128, 8, 255));

IEnumVARIANTPtr I = algo->GetImageEnumerator();
for (;;)
{
    _variant_t v;
    ULONG count = 0;
    if (FAILED(I->Next(1, &v, &count)) || count != 1)
        break;

    IImagePtr image(v.punkVal);
    uint8_t pixelValue = image->GetPixel(0, 0);
    if (image->Width == 320) {
        assert(pixelValue == 42);
    } else {
        assert(pixelValue == 255);
    }
}
Callback can be tricky. Here is example code that can log using ATL IDispEventImpl

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("A7673505-60FA-4DDA-91D8-A2CB609C19A1")]
public interface IProgress
{
    [DispId(1)] void Info(string msg);

    [DispId(2)] void Warn(string msg);
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComSourceInterfaces(typeof(IProgress))]
[Guid("3F8748C9-659D-4012-9467-CD49BCD39516")]
public class ProgressBase
{
    [ComVisible(false)]
    public delegate void LogFn(string msg);

    public event LogFn Info;
    public event LogFn Warn;

    protected void FireInfo(string msg)
    {
        if (Info == null) return;
        Info(msg);
    }

    protected void FireWarn(string msg)
    {
        if (Warn == null) return;
        Warn(msg);
    }
}

...
public interface IAlgorithm
{
    void Run(string arg);
}

...
public class ThresholdAlgorithm : 
  ProgressBase, IAlgorithm
{
  public void Run(string arg)
  {   
    if( arg == "bar")
    {
      FireWarn(
        "Warning:This algo does work well with bar");
    }

    FireInfo( string.Format(
      "Starting Algorithm with {0}", arg ));

...
            
    FireInfo( string.Format( 
      "Stopped Algorithm with {0}", arg ));
  }
}


#import 
  "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb" 
  named_guids no_namespace rename("_Module", "_NETModule")

#import "...\MyCompany.Lib.tlb" named_guids

_ATL_FUNC_INFO LogFnInfo = 
  { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };

class LogSink : public IDispEventImpl< 
  1, LogSink, &MyCompany_Lib::DIID_IProgress>
{
public:
  BEGIN_SINK_MAP(LogSink)
    SINK_ENTRY_INFO(1, MyCompany_Lib::DIID_IProgress, 
      1, OnInfo, &LogFnInfo)
    SINK_ENTRY_INFO(1, MyCompany_Lib::DIID_IProgress, 
      2, OnWarn, &LogFnInfo)
  END_SINK_MAP()

  LogSink(MyCompany_Lib::_ProgressBase* pbase)
  {
    m_ProgressBase = pbase;
    m_ProgressBase->AddRef();
    DispEventAdvise(m_ProgressBase);
  }

  ~LogSink()
  {
    m_ProgressBase->Release();
    DispEventUnadvise(m_ProgressBase);
   }

  void __stdcall OnInfo(BSTR msg)
  {
    _bstr_t bmsg(msg,false);
    cout << "Info : " << bmsg << endl;
   }

  void __stdcall OnWarn(BSTR msg)
  {
    _bstr_t bmsg(msg, false);
    cout << "Warn : " << bmsg << endl;
  }

private:
  MyCompany_Lib::_ProgressBase* m_ProgressBase;
};

using namespace MyCompany_Lib;
IAlgorithmPtr algo(__uuidof(ThresholdAlgorithm));
LogSink logger((_ProgressBase*)(IAlgorithm *)algo);

algo->Run(_bstr_t("foo"));
algo->Run(_bstr_t("bar"));


Info : Starting Algorithm with foo
Info : Stopped Algorithm with foo
Warn : Warning : This algo does work well with bar
Info : Starting Algorithm with bar
Info : Stopped Algorithm with bar

Thursday, May 10, 2018

C++/CLI to expose C++ code to C#

Define interface with C#. And also base class if needed.

    // IFoo.cs
    public interface IFoo
    {
        string Bar(int arg1, string arg2);
    }

    // FooBase.cs 
    public abstract class FooBase : IFoo
    {
        public virtual string Bar(int arg1, string arg2)
        {
            return arg1.ToString() + arg2;
        }
    }
Now C++/CLI code. First make Native C++ class - NativeFoo - that suit whatever need. Then define managed class Foo that sit between C++ and C# code. Note how the Foo::Bar() convert C# String to C++ std::string and vice versa.

// Foo.hpp
#include 

class NativeFoo
{
public:
	std::string Bar(int arg1, const std::string& arg2)
	{
		return arg2 + std::to_string(arg1);
	}
};

public ref class Foo : public FooBase
{
private:
	NativeFoo* m_Native;

public:
	Foo() 
		: m_Native( new NativeFoo )  
	{}

	~Foo()  
	{
		delete m_Native;
	}

	String^ Bar(int arg1, String^ arg2) override
	{
		std::string sarg2 = msclr::interop::marshal_as< std::string >(arg2);
		std::string bared = m_Native->Bar(arg1, sarg2);
		String^ ret = msclr::interop::marshal_as< String^ >(bared);
		return ret;
	}
};
Then the managed Foo can be created and Bar() can be used like any C# class.

  IFoo f = new Foo();
  string ret = f.Bar(42, "The answer is ");


Now callback from C++ to C#. First define callback in C# using delegate - OnFooFn.

    public delegate void OnFooFn(IFoo foo, string msg);

    public interface IFoo
    {
        OnFooFn OnFoo
        {
            get;
            set;
        }
    }
Then FooBase has a helper to call callback - FireOnFoo()

    public abstract class FooBase : IFoo
    {
...
        public OnFooFn OnFoo { get; set; }

        public void FireOnFoo( string msg)
        {
            if (OnFoo != null)
            {
                OnFoo( this, msg);
            }
        }
    }
Now native C++ class has a callback fn that will callback whatever call Bar().

class NativeFoo
{
public:
	std::string Bar(int arg1, const std::string& arg2)
	{
		m_FooFn("What is the question ?");
		return arg2 + std::to_string(arg1);
	}

	using CallbackFooFn = std::function< void(std::string) >;
	void SetCallbackFoo(CallbackFooFn fn) { m_FooFn = fn; }

private:
	CallbackFooFn m_FooFn = [](const std::string& arg) {};  // default dummy callback
};
Managed class can't set the above callback directly. It needs a bridge - CallbackBridgeFoo. Using this class, the C++ callback can be made through C#.

class CallbackBridgeFoo
{
private:
	NativeFoo* m_Native;
	gcroot< FooBase^ > m_CLR;  // FooBase has FireOnFoo()

public:
	CallbackBridgeFoo(NativeFoo* native, FooBase^ clr)
	{
		m_Native = native;
		m_CLR = clr;

		m_Native->SetCallbackFoo([this](const std::string& msg)
		{
			String^ smsg = msclr::interop::marshal_as< String^ >(msg);
			this->m_CLR->FireOnFoo(smsg);
		});
	}
};

public ref class Foo : public FooBase
{
private:
	NativeFoo* m_Native;
	CallbackBridgeFoo* m_Bridge;

public:
	Foo() 
		: m_Native( new NativeFoo )  
	{
		m_Bridge = new CallbackBridgeFoo(m_Native, this);
	}

	~Foo()  
	{
		delete m_Bridge;
		delete m_Native;
	}
...
};

Finally, C# can enjoy the C++ callback.

            IFoo f = new Foo();
            f.OnFoo = (sender, msg) => { Console.WriteLine(msg); }; 
            string ret = f.Bar(42, "The answer is ");   

Thursday, April 19, 2018

C++ template tutorial with code example

Parameterized Type


template < typename T >
class Vector 
{
private:
  T* elem;
  int sz;

public:
  explicit Vector(int s) 
  {
    elem = new T[s];
    sz = s;
  }

  T& operator[](int i) 
  {
    if (i < 0 || i >= size()) throw out_of_range("[i] is out of bound");
    return elem[i]; 
  }
};

{
  Vector< int > vi(200);
  vi[0] = 123;
  assert(vi[0] == 123);
}

{
  Vector< string > vs(17);
  vs[3] = "Hello";
  assert(vs[3] == "Hello");
}

{
  Vector< vector < int > > vli(45);
  vli[4] = vector({ 1, 2, 3 });
  assert(vli[4][1] == 2);
}

Function Template


template< typename T >
class Vector {
  // ...

  T* begin() const { return size() ? elem : nullptr; }
  T* end() const { return begin() + size(); }
};

template< typename Container, typename Value >
Value sum(const Container& c, Value v)
{
  for (auto x : c) v += x;
  return v;
}

{
  Vector< int > vi(4);
  vi[0] = 0; vi[1] = 1; vi[2] = 2; vi[3] = 3;
  double ds = sum(vi, 0.0);  // summation to double
  assert(ds == 6.0);

  int is = sum(vi, 0);  // summation to int
  assert(is == 6);
}

{
  list< double > ld;
  ld.push_back(3.0); ld.push_back(4.0);

  double ds = sum(ld, 0.0);
  assert(ds == 7.0);
}

Function Object


class Shape 
{
public:
  virtual void draw() = 0;
  virtual void rotate( double degree ) = 0;
};

class Rect : public Shape 
{
public:
  void draw() { cout << "rect"; }
  void rotate(double degree) { cout << "rotate"; }
};

class Circle : public Shape 
{
public:
  void draw() { cout << "circle"; }
  void rotate(double degree) {}
};

template< typename C, typename Oper >
void for_all(C& c, Oper op)
{
  for (auto& x : c) op(x);
}

vector< unique_ptr< Shape > > v;
v.push_back(make_unique< Rect >());
v.push_back(make_unique< Circle >());

for_all(v, [](unique_ptr< Shape >& s){ s->draw(); });
for_all(v, [](unique_ptr< Shape >& s){ s->rotate(45); });

Variadic Templates


void foo() { cout << endl; }

template< typename T >
void bar(T x) { cout << x << " "; }

template < typename T, typename ...Tail >
void foo(T head, Tail... tail) 
{
  bar(head);
  foo(tail...);
}

foo(1, 2, 2, "Hello");
foo(0.2, 'c', "World!", 0, 1, 2);

Function Specialization


template < class T>
T MyMax(T a, T b) 
{  
  return a > b ? a : b; 
}

template < >
const char* MyMax(const char* a, const char* b)
{
  return strlen(a) > strlen(b) ? a : b;
}


assert(MyMax(1, 2) == 2);
assert(MyMax("Morning", "Afternoon") == "Afternoon");

Function Specialization - Example


struct IO {
  int addr; 
  bool state;
};

struct Servo {
  int axis;
  double position;
};

struct Verify {
  template< typename T >
  static void Equal( T arg ) { throw exception("Should specialize"); }

  static void Equal(IO io) {
    cout << "check addr " << io.addr << " to be " << io.state << endl;
  }

  static void Equal(Servo s) {
    cout << "check axis " << s.axis << " position is at " << s.position << endl;
  }
};

Verify::Equal(IO{ 41, true });
Verify::Equal(Servo{ 3, 3.141592 });

Template Class Specialization - CompileTimeAssert


template< bool > struct CompileTimeAssert;
template< > struct CompileTimeAssert< true > {};

// CompileTimeAssert< sizeof(uint32_t) == 2  >();
CompileTimeAssert< sizeof(uint32_t) == 4 >();

// CompileTimeAssert< std::is_base_of::value >();
CompileTimeAssert< std::is_base_of::value >();

static_assert(std::is_base_of< Shape, Rect >::value, “Rect is a Shape");

Template Class Specialization - TypeTrait


template< typename T >
  struct IsVoid {
  static const bool value = false;
};

template< >
  struct IsVoid< void >{
  static const bool value = true;
};

template< typename T >
  struct IsPointer{
  static const bool value = false;
};

template< typename T >
  struct IsPointer< T* >{
  static const bool value = true;
};

CompileTimeAssert< IsVoid< void >::value >();
// CompileTimeAssert< IsVoid< int >::value >();

CompileTimeAssert< IsPointer< Shape* >::value >();
// CompileTimeAssert< IsPointer< Shape >::value >();

static_assert( is_pointer< Shape* >::value, "Shape* should be a pointer");

smart pointer to release resource automatically


class FILEReleasePolicy
{
public:
 static void release(FILE* fp) { fclose(fp); }
};

using FILEPtr = Poco::SharedPtr;
{
  FILEPtr fp = fopen("temp.txt", "wt");
  fprintf(fp, "hello world");
}

Sunday, April 1, 2018

C++11,14 tutorial with code example

Initializer with default constructor

 struct Foo {
  int Bar; string Too;
 };

 Foo a = { 1234, "Hello" };
 // Foo b( 1234, "Hello" );   // compile error

 vector c = {
  { 1234, "Hello" },
  { 4321, "World" },
  { 1111, "Good Morning" }
 };
When defined a constructor, the default constructor can't be used.

 struct Foo {
  int Bar; string Too;
  Foo(int bar) : Bar(bar) {}
 };

 // Foo a = { 1234, "Hello" };   // compile error
 Foo b{ 1234 };   
 Foo c(1234);
std::initializer usage

 struct Foo {
  int sum(const std::initializer_list< int >& list) {
   int total = 0;
   for (auto& e : list) {
    total += e;
   }
   return total;
  }
 };
 Foo foo;

 auto list = { 1, 2, 3 };
 assert(foo.sum(list) == 6);
 assert(foo.sum({ 1, 2, 3 }) == 6);
 assert(foo.sum({}) == 0);
lvalue and rvalue

 int a = 42;
 int b = 43;

 // a and b are both l-values:
 a = b; // ok
 b = a; // ok
 a = a * b; // ok

 // a * b is an rvalue:
 int c = a * b; // ok, rvalue on right hand side of assignment
 // a * b = 42; // error C2106: '=' : left operand must be l-value
Function return is rvalue but can be lvalue if reference returned.

 int someValue = { 1212 };
 int& foo() { return someValue; }
 int foobar() { return someValue; }

 // lvalues:
 int i = 42;
 i = 43; // ok, i is an lvalue
 int* p = &i; // ok, i is an lvalue
 foo() = 42; // ok, foo() is an lvalue
 int* p1 = &foo(); // ok, foo() is an lvalue

 // rvalues:
 int j = 0;
 j = foobar(); // ok, foobar() is an rvalue
//  int* p2 = &foobar(); // error C2102: '&' requires l-value
 j = 1234; // ok, 42 is an rvalue
Resolving function when argument is reference and universal reference.

 struct FooA { int X = 1234; };
 FooA RunFooA(const FooA& a) { FooA temp = a; temp.X = 4321; return temp; }
 FooA RunFooA(FooA&& a) { a.X = 4321; return a; }


 FooA a;
 FooA b = RunFooA(a);
 FooA c = RunFooA(FooA());
 FooA d = RunFooA(std::move(a));
transfer ownership of std::unique_ptr using std::move

 std::unique_ptr p1{ new int };
// std::unique_ptr p2 = p1; // error -- cannot copy unique pointers
 std::unique_ptr p3 = std::move(p1); // move `p1` into `p2`
       // now unsafe to dereference object held by `p1`
auto type resolution

 auto a = 3.14; // double
 auto b = 1; // int
 auto& c = b; // int&
 auto d = { 0 }; // std::initializer_list
 auto&& e = 1; // int&&
 auto&& f = b; // int&
 auto g = new auto(123); // int*
 delete g;
 const auto h = 1; // const int
 auto i = 1, j = 2, k = 3; // int, int, int
 // auto l = 1, m = true, n = 1.61; // error -- `l` deduced to be int, `m` is bool
 // auto o; // error -- `o` requires initializer
no more typing iterator type

 std::vector v = { 1, 2, 3, 4 };
 std::vector::const_iterator cit1 = v.cbegin();
 auto cit2 = v.cbegin();
auto return type using decltype

 template 
 auto AddAnyTwo(X x, Y y) -> decltype(x + y) {
  return x + y;
 }


 assert(AddAnyTwo(1, 2) == 3);
 assert(AddAnyTwo(1, 2.0) == 3.0);
 assert(AddAnyTwo(1.5, 1.5) == 3.0);
lambda

 int LBar = 1;

 auto getLBar = [=]{ return LBar; };
 assert(getLBar() == 1);

 auto addLBar = [=](int y) { return LBar + y; };
 assert(addLBar(1) == 2);

 auto getLBarRef = [&]() -> int& { return LBar; };
 getLBarRef() = 2;
 assert(LBar == 2);
lambda capture - reference or not

 int x = 1;
 auto f1 = [&x] { x = 2; }; // OK: x is a reference and modifies the original
 f1();

 // auto f2 = [x] { x = 2; }; // ERROR: the lambda can only perform const-operations on the captured value
 auto f3 = [x]() mutable { x = 2; }; // OK: the lambda can perform any operations on the captured value
 f3();
using as alias

 template  using Vec = std::vector;

 Vec v{}; // std::vector

 using String = std::string;
 String s{ "foo" };
nullptr

 struct Foo
 {
  void Bar(int) {}
  void Bar(char*) {}
 };

 Foo foo;
 foo.Bar(NULL);  // should throw error but not with VS2013
 foo.Bar(nullptr);
unspecified enum is just a number

 enum Week { Monday = 0, Tuesday, Thursday };
 enum Month { January = 0, Feburary,  };

 Month m = January;

 if (m == Monday)
 {
  // danger !!!
  m = Feburary;
 }

// Specifying underlying type as `unsigned int`
 enum class Color : unsigned int { Red = 0xff0000, Green = 0xff00, Blue = 0xff };
  
 // `Red`/`Green` in `Alert` don't conflict with `Color`
 enum class Alert : bool { Red = false, Green };
  
 Color redColor = Color::Red;
 Alert redAlert = Alert::Red;

 // bool isSame = (redColor == redAlert); 
 // error C2678: binary '==' : no operator found which takes a left-hand operand of type 'CPPTest::testStrongTypedEnum::Color' 
 // (or there is no acceptable conversion)

delegating constructor

 struct Foo {
  int foo;
  Foo(int foo) : foo(foo) {}
  Foo() : Foo(1) {}
 };

 Foo foo{};
 assert( foo.foo == 1 );
be more explicit on function overriding

 struct A {
  virtual void foo() {}
  void bar() {}
 };

 struct B : A {
  void foo() override {};  // correct -- B::foo overrides A::foo
  // void bar() override {}; // error C3668 : 'CPPTest::testOverrides::B::bar' : method with override specifier 'override' did not override any base class methods
  // void baz() override {}; // error C3668 : 'CPPTest::testOverrides::B::baz' : method with override specifier 'override' did not override any base class methods
 };
say final to stop overriding

 struct A {
  virtual void foo() {}
 };

 struct B : A {
  virtual void foo() final {}
 };

 struct C : B {
  // virtual void foo() {} // error C3248: 'CPPTest::testFinal::B::foo': function declared as 'final' cannot be overridden by 'CPPTest::testFinal::C::foo'
 };
say final to stop inheritance

 struct A final {};

 // error C3246: 'CPPTest::testFinal1::B' : cannot inherit from 'CPPTest::testFinal1::A' as it has been declared as 'final'
 // struct B : A {};
delete to stop compiler generating default methods

#pragma warning( push )
#pragma warning( disable : 4822)

 class A {
  int x;

 public:
  A(int x) : x(x) {};
  A(const A&) = delete;
  A& operator=(const A&) = delete;
 };

 A x{ 123 };
 // A y = x; // error C2280: 'CPPTest::testDeletedFunction::A::testDeletedFunction::A(const CPPTest::testDeletedFunction::A &)' : attempting to reference a deleted function
 // y = x; // error -- operator= deleted

#pragma warning( pop )
range based iteration

 std::vector a{ 1, 2, 3, 4, 5 };
 for (int& x : a) 
 { 
  x *= 2; 
 }
 // a == { 2, 4, 6, 8, 10 }

 for (int x : a) 
 {
  x *= 2;
 }
 // a == { 2, 4, 6, 8, 10 }

 int b[] = { 5, 4, 3, 2, 1 };
 for (int& x : b)
 {
  x *= 3;
 }
std::to_string

 assertEqual("123", std::to_string(123));
 assertEqual("1.200000", std::to_string(1.2));
std::unique_ptr

 
 {
  std::unique_ptr p1{ new int };
  *p1 = 1234;
  assert(*p1 == 1234);
 }

 {
  int *p1 = new int;
  *p1 = 1234;
  assert(*p1 == 1234);
  delete p1;
 }
std::unique_ptr and struct

 
 struct Foo { int Bar; string Too; };
 std::unique_ptr p1{ new Foo };
 p1->Bar = 1234;
 p1->Too = "hello";

 assert(p1->Bar == 1234);
 assert(p1->Too == "hello");
std::make_unique

 struct Foo {
  Foo(int bar, string too) : Bar(bar), Too(too){}
  int Bar; string Too;
 };
 std::unique_ptr p1;

 if (p1 == nullptr)
 {
  // p1 = new Foo;  // compile error 
  p1 = std::unique_ptr(new Foo(1234, "Hello"));
  p1 = std::make_unique(1234, "Hello");
 }
unique_ptr to vector

 struct Foo {
  Foo(int bar, string too) : Bar(bar), Too(too){}
  int Bar; string Too;
 };
 vector< std::unique_ptr > Foos;
 Foos.push_back(std::unique_ptr(new Foo(1234, "Hello")));
 Foos.push_back(std::make_unique(4321, "World"));
 Foos.push_back(std::make_unique(1111, "Good Morning"));
std::shared_ptr

 struct Foo { int Bar = 1234; string Too = "Hello"; };
 std::shared_ptr p1{ new Foo };
 p1->Bar = 4321;

 std::shared_ptr p2 = p1;
 p2->Too = "World";

 assertEqual("World", p1->Too);

 auto p3 = make_shared();
 assertEqual(1234, p3->Bar);

 p1 = p3;
unique_ptr to shared_ptr

 struct Foo { int Bar = 1234; string Too = "Hello"; };
 std::unique_ptr p1( new Foo );

 // std::shared_ptr p2 = p1; 
 // error C2440 : 'initializing' : cannot convert from 'std::unique_ptr< CPPTest::testSharedPtr1::Foo,std::default_delete <_Ty> >' 
 // to 'std::shared_ptr'

 std::shared_ptr p3 = std::move(p1); 

 // p1 is dangling now
tuple

 // `playerProfile` has type `std::tuple`.
 auto playerProfile = std::make_tuple(51, "Frans Nielsen", "NYI");
 assertEqual( 51, std::get<0>(playerProfile)); 
 assertEqual( "Frans Nielsen", std::get<1>(playerProfile));
 assertEqual( "NYI", std::get<2>(playerProfile)); 
tie

// With tuples...
 std::string playerName;
 std::tie(std::ignore, playerName, std::ignore) = std::make_tuple(91, "John Tavares", "NYI");
 assertEqual("John Tavares", playerName);

 // With pairs...
 std::string yes, no;
 std::tie(yes, no) = std::make_pair("yes", "no");
 assertEqual("yes", yes);
 assertEqual("no", no);

Thursday, January 18, 2018

Aritificial neural network tutorial with C++ and OpenCV

Here is a tutorial of ANN with C++ and OpenCV. This is based on the book 'An Introduction to Machine Learning' by Miroslav Kubat.

ANN consists of nodes, connection and bias. Nodes fires input signal nonlinearly. Connections are weights between nodes which increase or decrese signal. And there are bias that charaterize the network - what a biased comment on bias !


With inputs on the network, the output generated by going through the network - called forward propagation.

Mat ForwardPropagation(const Mat& X, const Mat& HN, const Mat& ON, const Mat& HB, const Mat& OB, Mat& H)
{
 auto sigmoid = [](double &v, const int* pos) {
  v = 1.0 / (1.0 + exp(-v)); 
 };

 H = HN * X;
 H.forEach([=](double &v, const int* pos) { v += HB.at(pos[0]); });
 H.forEach(sigmoid);
 Mat O = ON * H;
 O.forEach([=](double &v, const int* pos) { v += OB.at(pos[0]); });
 O.forEach(sigmoid);

 return O;
}


After forward propagation , network weight and bias can be adjusted by backward-propagation.

void BackwardPropagation(
 const Mat& X, Mat& HN, Mat& ON, Mat& HB, Mat& OB, const Mat& H, 
 const Mat& Y, const Mat& T, double nu )
{
 Mat D1 = Y.clone();
 D1.forEach([=](double &yi, const int* i) {
  double ti = T.at(i);
  yi = yi * (1 - yi) * (ti - yi);
 });

 Mat P = ON.t() * D1;
 Mat D2 = H.clone();
 D2.forEach([=](double &hi, const int*i) {
  double pi = P.at(i);
  hi = hi * (1 - hi) * pi;
 });

 for (int x = 0; x < H.cols; ++x)
 {
  ON += nu * D1.col(x) * H.col(x).t();
  OB += nu * D1.col(x);
  HN += nu * D2.col(x) * X.col(x).t();
  HB += nu * D2.col(x);
 }
}


To train, one of data at web can be used. Here http://archive.ics.uci.edu/ml/datasets/steel+plates+faults is the one used in here.

enum class Direction {
 Row = 0,
 Column = 1,
};

template< typename T> 
void Normalize(Mat& m, Direction dir = Direction::Row )
{
 int count = dir == Direction::Row ? m.rows : m.cols;
 auto getVector = [dir](Mat& m, int i) { return dir == Direction::Row ? m.row(i) : m.col(i); };
  
 for (int i = 0; i < count; ++i)
 {
  Mat X = getVector( m, i );
  auto r = minmax_element(X.begin(), X.end());
  T minv = *r.first, maxv = *r.second;

  X.forEach([=](T &x, const int* pos) { x = (T)(2*(x-minv) / (maxv-minv) - 1.0); });
 }
}

double AverageDistance(const Mat& E )
{
 double sum = 0.0;
 for (int j = 0; j < E.cols; ++j)
 {
  Mat ej = E.col(j);
  sum += sqrt(ej.dot(ej));
 }
 return sum / E.cols;
}


Mat D = ReadMat("SteelPlateFaults.txt", " \t");
D = D.rowRange(0, 340);

Mat X = D.colRange(4, 27).t();
Normalize(X);
Mat T = D.colRange(27, 29).t();

int M = T.rows, N = X.rows;
Mat HN(N + 1, N, CV_64FC1, Scalar(0.01));
Mat HB(N + 1, 1, CV_64FC1, Scalar(0.0));
Mat ON(M, N + 1, CV_64FC1, Scalar(0.01));
Mat OB(M, 1, CV_64FC1, Scalar(0.0));

Mat H, Y;
for (int i = 0; i < 100; ++i)
{
 Y = ForwardPropagation(X, HN, ON, HB, OB, H);
 BackwardPropagation(X, HN, ON, HB, OB, H, Y, T, 0.1);

 printf("iteration %d, Error %.3f\n", i, AverageDistance(T-Y));
}

printf( "Trained Error %.3f\n", AverageDistance(T - Y));

iteration 0, Error 0.708
iteration 1, Error 0.748
iteration 2, Error 0.814
…
iteration 98, Error 0.095
iteration 99, Error 0.090
Trained Error 0.090


There is Machine Learning module in OpenCV. Here above code can be simplified like below. The forward and backward propagation are done in the ANN_MLP::train(). ANN_MLP::predict() does forward propagation only.

int BestIndex(const Mat& x )
{
 auto mpi = max_element( x.begin(), x.end());
 return (int)distance( x.begin(), mpi);
}

using namespace cv::ml;

...
Ptr mlp = ANN_MLP::create();

Mat layer = (Mat_(3, 1) << X.cols, 60, T.cols);
mlp->setLayerSizes(layer);
mlp->setActivationFunction(ANN_MLP::ActivationFunctions::SIGMOID_SYM);
mlp->setTermCriteria(TermCriteria( 
  TermCriteria::Type::COUNT + TermCriteria::Type::EPS, 100000, 0.01 ));
mlp->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP);

Ptr trainingData = TrainData::create( X, SampleTypes::ROW_SAMPLE, T );
bool isTrained = mlp->train(trainingData);

int sum = 0;
for (int i = 0; i < X.rows; i++) {
 Mat result; mlp->predict( X.row(i), result);
 int pi = BestIndex(result);
 int ti = BestIndex(T.row(i));
 sum += (pi == ti ? 1 : 0);
}

printf("%d/%d matched : %.1f accuray\n", sum, T.rows, ((double)sum / T.rows) * 100.0);

335/340 matched : 98.5 accuray

Wednesday, January 10, 2018

Find translation between two images in sub pixel

To find a translation - x, y offset - between two images is called image registration - https://en.wikipedia.org/wiki/Image_registration. After finding out the translation, image difference can be applied to see if there is any defect on the object.

Here above are target images come from patterned glass - original image is around 1000 pixels in short dimension but are reduced to blur any specific feature.

There can be number of methods but in here, optimization - coordinate search - is tried and here is related code snippet. https://en.wikipedia.org/wiki/Coordinate_descent. Code is based on the opencv Mat class. The usage of unit matrix u and integer variable i and j are beautiful. Refer the comment around the usage.


 void Optimize(InputArray x0, OutputArray xn)
 {
  int maxIter = GetValue("MaxIteration");
  double delta = GetValue("Delta");
  double eps = GetValue("TerminalEpsilon");

  Mat xk = x0.getMat().t();
  int N = xk.rows;
  Mat u = Mat::eye(N, N, CV_64FC1);
  hconcat(u, -u, u);  // for each dimension, search in positive and negative direction
  int i = 0;
  double fxk = m_Callback->Function(xk);

  int iter = 0;
  while (iter++ < maxIter)
  {
   int j = 0;
   for (; j < u.cols; ++j)
   {
    i = (i + j) % u.cols;
    Mat xki = xk + u.col(i) * delta;
    double fxki = m_Callback->Function(xki);  // user says score of the move

    if (fxki < fxk)  
    {
     xk = xki;
     fxk = fxki;
     break;  // if found better score, try next dimension
    }
   }

   if (j == u.cols)
   {
    delta /= 2;   // make small delta as there is no better score found with current delta 
   }

   if (delta < eps)
    break;
  }

  xn.create(xk.rows, xk.cols, xk.type());
  xk.copyTo(xn);

  SetValue("IterationCount", iter);
  SetValue("Minimum", fxk);
 }



To say the score of each move, sub-pixel image difference can be calculated; If two image are matched, the difference will be near zero. If not, it will go up.
Going through every pixel of image and calculate sub-pixel difference is an expensive operation. Here is code snippet that does the comparison in SIMD using intrinsic code. Every loop, 8 pixels are differenced in fixed-point arithmatic.


struct TranslationInSub
{
 int NX, NY;
 double FX, FY;

 static TranslationInSub FromPoint(const cv::Point2d& t)
 {
  TranslationInSub r = { (int)floor(t.x), (int)floor(t.y), 0, 0 };
  r.FX = t.x - r.NX;
  r.FY = t.y - r.NY;
  return r;
 }
};

template< typename T >
struct WeightCompass
{
 T NW, NE, SW, SE;

 static WeightCompass< T > FromTranslation(const TranslationInSub& t, double scale )
 {
  WeightCompass< T > r =
  {
   (T)boost::math::round((1.0 - t.FX)*(1.0 - t.FY) * scale),
   (T)boost::math::round(t.FX*(1.0 - t.FY) * scale),
   (T)boost::math::round((1.0 - t.FX)*t.FY * scale),
   (T)boost::math::round(t.FX*t.FY * scale)
  };

  return r;
 }
};

struct WeightCompassSMM
{
 __m128i NW, NE, SW, SE;

 static WeightCompassSMM FromWeightCompass( const WeightCompass< uint16_t >& f)
 {
  WeightCompassSMM  r;
  
  uint16_t fNWSE[8];
  fill(fNWSE, fNWSE + 8, f.NW);
  r.NW = _mm_loadu_si128((__m128i *)fNWSE);
  fill(fNWSE, fNWSE + 8, f.NE);
  r.NE = _mm_loadu_si128((__m128i *)fNWSE);
  fill(fNWSE, fNWSE + 8, f.SW);
  r.SW = _mm_loadu_si128((__m128i *)fNWSE);
  fill(fNWSE, fNWSE + 8, f.SE);
  r.SE = _mm_loadu_si128((__m128i *)fNWSE);

  return r;
 }
};

int Details::DiffSumBySIMD( const cv::Mat& ref, const cv::Mat& tar, cv::Rect roi, cv::Point2d t)
{
 const uint16_t SCALE = 0x40; // scale to convert 8 bits gray level to 16bit fixed point float  

 TranslationInSub tN = TranslationInSub::FromPoint(t);
 const WeightCompass< uint16_t > fN = WeightCompass< uint16_t >::FromTranslation(tN, SCALE);
 const WeightCompassSMM mfN = WeightCompassSMM::FromWeightCompass(fN);

 int sum = 0;
 const __m128i mZero = _mm_setzero_si128();

 uint16_t ps[8];

 for (int y = roi.y; y < (roi.y + roi.height); y++)
 {
  const uint8_t* PC_C = ref.ptr(y, roi.x);  // reference image 
  const uint8_t* PN_NW = tar.ptr(y + tN.NY, roi.x + tN.NX);  // target image at translation offset - integer

  for (int x = roi.x; x < (roi.x+roi.width); x += 8, PC_C += 8, PN_NW += 8)
  {
   __m128i mC = _mm_loadu_si128((__m128i *)PC_C);  
   mC = _mm_unpacklo_epi8(mC, mZero);
   mC = _mm_slli_epi16(mC, 6);   // load 8 pixels as 16 bits fixed point float

   __m128i mPN = mZero;
   __m128i mP = _mm_loadu_si128((__m128i *)PN_NW);   // North West
   mP = _mm_unpacklo_epi8(mP, mZero);
   mP = _mm_mullo_epi16(mP, mfN.NW);
   mPN = _mm_adds_epu16(mPN, mP);

   mP = _mm_loadu_si128((__m128i *)(PN_NW + 1));    // North East
   mP = _mm_unpacklo_epi8(mP, mZero);
   mP = _mm_mullo_epi16(mP, mfN.NE);
   mPN = _mm_adds_epu16(mPN, mP);

   mP = _mm_loadu_si128((__m128i *)(PN_NW + tar.cols));  // South West
   mP = _mm_unpacklo_epi8(mP, mZero);
   mP = _mm_mullo_epi16(mP, mfN.SW);
   mPN = _mm_adds_epu16(mPN, mP);

   mP = _mm_loadu_si128((__m128i *)(PN_NW + tar.cols + 1));  // South East
   mP = _mm_unpacklo_epi8(mP, mZero);
   mP = _mm_mullo_epi16(mP, mfN.SE);
   mPN = _mm_adds_epu16(mPN, mP);

   __m128i mDiff = _mm_abs_epi16(_mm_subs_epi16(mC, mPN));
   mDiff = _mm_srai_epi16(mDiff, 6);

   __m128i mPartialSum = _mm_sad_epu8(mDiff, mZero);
   _mm_storel_epi64((__m128i *)(ps), mPartialSum);

   sum += (ps[0] + ps[3]);
  }
 }

 return sum;
}



Above methodology were at a proposal on a reserch project on some company but didn't launched up so just open in here.