Advanced Programming with Modern C++ 23 for Image Processing

Update March 2022 - 1401

make industrial process scale-ups successful

#c++23 #optimization #imageprocessing #deeplearning #AI #IoT


You need latest version of C++ compiler in order to use C++ 20 standard. GCC>12 or CLang>13. CUDA 11 support C++17 by nvcc; Cmake.

call by value: on stack

  • void f(int a) { a++; } //a in main not change

call by reference:

  • void f(int *p); // f(&i);

  • void f(int &i);// f(i)

  • void func(const std::string & s) { s.c_str() } // func(s);


struct default is public (use when we have only data members) and class default is private (when also have function members) .

  • function's signature // int getvalue() const;


  • // ! this is a very critical comment

  • // * this is a highlighted comment

  • // TODO: this is a TODO comment

  • // ? this is a question comment

Creational design patterns:

  • flexible, maintainable, extensible

  • gang of four "design patterns: elements of reusable object oriented software"

  • 23 patterns

    1. creational (5) : object instantiation

      1. factory method

        • composition: property referenced by another class

        • inheritance: class extends another class

      2. abstract factory

      3. builder : complex

      4. prototype: clone

      5. singleton: only one instance

    2. structural : class relationships and hierarchies; class pattern: is; structural object patterns: has

      1. adapter

      2. bridge

      3. composite

      4. decorator

      5. facde

      6. flyweight

      7. proxy

    3. behavioral (12): object intercommunication :

      1. chain of responsibility

        • password check

      2. command

        • one button for all command

      3. mediator

        • reduce dependency : married -> spouse name -> ....

      4. observer

        • std::vector<Subscriber*> subscribers;

        • this->subscribers.push_back(subscriber);

        • void unsubscribe(Subscriber *subscriber) override {
          subscribers.erase(std::remove_if(subscribers.begin(),subscribers.end(),
          [subscriber](Subscriber *s){{return s->getName() ==
          subscriber->getName(); }), subscribers.end());

      5. interpreter

        • 1+(2+3)

      6. state

        • order


      7. strategy

      8. template method

      9. visitor

      10. iterator pattern

      11. memento

        • undo

      12. null-object

        • default



UML: unified modeling language

abstract and concrete classes



LinkedIn:

  • int x=5;

  • size_t y=sizeof x; or sizeof(int)

  • printf("sizeof x is %zd\n",y*8); //change bit to byte


  • func(){ static int i=5; }// it will change ++ // it will be on static storage not stack


  • void (*pfunc)()=func;

  • (*pfunc)();


  • #include <cstdio>

  • #include <cstdarg> // variadic argument

  • double average(const int count, ...) { va_list ap; va_start(ap,count); va_arg(ap,double); va_end(ap); }


  • template <typename T>

    • larger executables

    • confusing error messages

    • longer compile times

  • #include<cerrno>

  • perror("");//


  • v.begin(); v.end(); v.size(); v.back(); v[5]; v.at(5)

  • string: s.size(); s.length(); s.find();

  • std::hex,showbase, oct, fixed, scientific,setprecision(3), floatfield,setw, setfill('-'); std::cin.getline(buf,sizeof(buf));

  • #include<exception> try { ; } catch (std::exception & e) { e.what() }


  • class1 * o1= new(nothrow) c1[5]; if (o1==nullptr){}; delete [] o1;

  • if we don't want to create base class we can put constructor in the private part classname(){}

  • then use constructor in the protected: classname( ): _name(value) {}

  • using friend class nameofsubclass; to use private functions ; friend class base;

  • virtual : maybe overloaded and maybe write in subclass; we need ~


  • #include <memory>

  • std::unique_ptr<struct> a(new struct());

  • auto b=std::make_unique<struct>();

    • a.reset(new structure()); // delete

    • auto c=std::move(b); // b is null

    • c.release();

    • auto a=std::make_shared<struct>();

    • auto w1=std::weak_ptr(struct>();


  • T & x => lvalie reference

  • T && y => rvalue reference

  • rule of five (if you define any of these functions you need to define all)

    • ~class();

    • class(class &);

    • class(class &&);

    • class & operator = (class &);

    • class & operator = (class &&);

  • []()->char{}

    • auto fp=[]<typename T>(const T & n)-> T {return n*5; };

  • #define MAX(a,b) (a>b ? a:b)

  • constexpr int ONE =1;


  • unit tests



  • virtual Class *clone()= 0 ;

              • template<auto n>

              • struct B { /* ... */ };




lambda capture

Module Interface Unit : *.cppm

Module Implementation Unit: *.cpp




Important commands

Compile CUDA for Jetson Nano (JetPack 4.5, CUDA 10.2)

nvcc -std=c++14 -arch=sm_62 -o main.run main.cu

compile c++ 20; based on GCC 12, CLang 13

clang++ -std=c++2a -c helloworld.cpp -Xclang -emit-module-interface -o helloworld.pcm

clang++ -std=c++2a -stdlib=libc++ -fimplicit-modules -fimplicit-module-maps -fprebuilt-module-path=. main.cpp helloworld.cpp

commands

  1. echo "export PATH=.:"$PATH"" >> ~/.bashrc

  2. source ~/.bashrc

  • htop

  • ulimit -a

  • git submodule add (githuburl external/glfw)

Tools

brew install --HEAD LouisBrunner/valgrind/valgrind

valgrind ./a.out


CppCon 2016: John Lakos "Advanced Levelization Techniques (part 1 of 3)





Large Scale C++ software design

  • retain control of your dependency graph

  • keep concerns separated

  • make modules reusable in other contexts at minimal cost

appendix

C++ design patterns: factory method

  • class c1

  • {

  • public:

    • void c1_test()

    • {

      • cout << "main class" << endl;

    • }


  • };

  • class c2:public c1

  • {

  • public:

    • c2()

    • {

      • cout << "c2" << endl;

    • }


  • };

  • class c3 :public c1

  • {

  • public:

    • c3()

    • {

      • cout << "c3" << endl;

    • }


  • };

  • class factory

  • {

  • private:

      • c1 * _c1;

  • public:

    • c1 * function_factory(int i)

    • {

      • switch (i)

      • {

      • case 1:

        • return new c2;

        • break;

      • case 2:

        • return new c3;

        • break;


      • }

    • }



  • };

  • int main()

  • {

    • factory f;

    • c1* c;

    • c = f.function_factory(2);

    • return 1;

  • }

  • 1

      • error : Access violation writing location for clone image from std::vector<cv::Mat> and findHomography

      • can not use std::vector<cv::Mat> imagesF; imagesF.at(0) or imagesF[0] or imagesF[0].clone()

      • Mat is some kind of smart pointer for the pixels, so Mat a=b will have shared pixels for a and b. similar situation for push_back()

      • if you need a 'deep copy', use Mat::clone(): imagesF.push_back(imageMat.clone()); https://stackoverflow.com/a/19524261/3533188


When you are using vector to store image from OpenCV Mat you need to use deep copy because cv::Mat is like smart pointer.

  • std::vector<cv::Mat> imagesVector;

  • imagesVector.push_back(imageMat.clone());

  • cv::Mat im_in = imagesVector[0]


#OpenCV #C++ #tiziran

Download first draft for OpenCV 5 book : https://docs.google.com/document/d/1v3qRJE8d0rYXrfDf_BjJHXANTKsPu2lw6In32gD88wY/edit?usp=sharing