Course notes: OpenCV/C++

Preamble

Notes from LEARN OPENCV C++ in 4 HOURS | Including 3x Example Projects Win/Mac (2021)

Github: murtazahassan/Learn-OpenCV-cpp-in-4-Hours

See also

Related courses – videos

Links


Notes from OpenCV/C++ video course

Intro

  • pixels,
  • Resolution
      • VGA 640×480,
      • HD 1280×720,
      • FHD 1920×1080,
      • 4k 3840 x 2160
  • binary image (B&W),
  • greyscale,
  • RGB (three greyscales, one each for red, green and blue 640×480 x 3)

Software

Windows

  • Step 1: Installation
  • Visual Studio  > Select “Desktop Development for C++”
  • OpenCV
  • Install openCV> github>releases>opencv-4.5.0-vc14_vc15.exe
  • Step 2: Path
  • Check installation path (i.e. C: or D:)
  • Add to the environment variable Path, this path: D:\opencv\build\x64\vc15\bin
  • System Properties>Environment Variables…>Path
  • Restart
  • Step 3: New Project
  • In VS, create new C++ console project (Select Empty Project> Name: OpenCVCourse)
  • Choose x64 in the menu of VS
  • Step 4: Paths
  • Click on Project, then menu Project>Properties>VC++ Directories>
  • Add build path to “Include Directories”, D:\opencv\build\include
  • Add library path to “Libraries Directories”, D:\opencv\build\includex64\vc15\lib
  • Add linker path to library (Project>Properties>Linker>Input>Additional Dependencies) (opencv_world450d.dllopencv_world450d.lib). Note that the d at the end of the library name is for the debug version (use the debug version whilst coding). Use, i.e. replace, .lib and not .dll. Full path is D:\opencv\build\x64\vc15\bin\opencv_world450d.lib
  • Step 5 : Test the code
  • Right click project>Add>New Item…>C++File>Name:Test (.cpp not required)
  • Copy and paste the code below into test.cpp
  • Right click project>Open folder in File Explorer (at the bottom)
  • Copy the resources folder into the project folder
  • Run: Click on Load windows Debugger (play button)

Testcode – Image Display

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

////// Images //////
int main() {
    string path = "Resources/test.png";
    Mat img = imread(path);
    imshow("Image", img);
    waitKey(0);
    return 0;
}

Mac

  • Visual Studio (Mac OSX 10.13.6) > Select “Desktop Development for C++”
  • OpenCV (4.5.1 iOS)
  • Xcode
  • Step 1 Install brew
  • Step 2: Install opencv
  • brew install opencv
  • Open Xcode
  • Step 3: Create Xcode project
  • macOS – terminal
  • C++ (not Swift)
  • Name project
  • Need to state Organisation Identifier – random string
  • Step 4: Add Dynamic Libraries
  • Right click project> Add Files to “OpenCV_Course”…> Press “/”>/usr/local/Cellar/opencv/>lib>Select all Dynamic Libraries>Add
  • The libraries will appear in the left hand pane of the Project Navigator.
  • Doing this, automatically, adds /usr/local/Cellar/opencv/4.5.1_3/lib to the Library Search Path,
  • Step 5: Add header search path
  • Go to Build Settings, ensure that All and Combined are selected, and search for “Header Search Paths”
  • Add /usr/local/Cellar/opencv/4.5.0.5/include/opencv4
  • I have 4.5.1_3: /usr/local/Cellar/opencv/4.5.1_3/include/opencv4
  • Double click Header search paths on the right and paste path
  • make sure recursive, not non-recursive in the menu
  • Step 6 Enable resource folder access
  • Put the Resources folder in the folder with the main.cpp file.
  • Click OpenCV_Course at the top of the window next to the play button_
  • Select edit Scheme
  • Under Run/Debug
  • Check Working Directory: Use custom working directory
  • Select your project folder, with main.cpp in it
  • Step 6.5 Run test code
  • Copy and pate into main.cpp
  • Hit run.
  • Loads of  warnings (documentation) and one error (double click the error to see the actual error (at the bottom)).
  • Step 7: Enable access to camera
  • File – New File
  • Select “Property list” in “Resources”>Next>Name:Info>Create
  • The new info.plist will be visible in the left hand pane of the Project Navigator
  • Double click it
  • Click the plus sign to the right of Root
  • which adds a new item. Double click the key and the value fields and paste in the entries below
  • Key: NSCameraUsageDescription
  • Value: $(PRODUCT_NAME) camera use
  • Right click the project “OpenCV_Course”>Show in Finder. You will see the plist file
  • Right click the executable “OpenCV_Course” under Products (at the bottom of the Project Navigator)>Show in Finder.
  • Open Products folder and right click on the file with your project name and show in Finder
  • Drag your info.plist file to this folder

Testcode – Webcam

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

////// Webcam //////
int main() {
    VideoCapture cap(0);
    Mat img;

    while (true) {
        cap.read(img);
        imshow("Image", img);
        waitKey(1);
    }
    return 0;
}

An aside: Random initial test build error

I immediately got the following error when compiling the first “image display” testcode:

Apple Mach-O Linker (ld) Error Group:
ld: library not found for -lcrypto.41
clang: error: linker command failed with exit code 1 (use -v to see invocation)

There is only one crypto on my system:

$ find /usr/local -name crypto
/usr/local/Cellar/rust/1.49.0_1/share/doc/rust/html/core/core_arch/aarch64/crypto

However, there is

/usr/local/Cellar/openssl\@1.1/1.1.1j/lib/libcrypto.dylib

This answer to Xcode 8 and “ld: library not found for -lcrypto” suggests adding:

$(SRCROOT)/../../openssl-1.0.1s-MacOSX/lib

to Build Settings: Library Search Paths.

Adding the path didn’t help as the version is incorrect.

brew install openssl reported that openssl is up to date. I could not find any reference to version 41 anywhere online, so I thought that I’d trying faking it. In /usr/local/Cellar/openssl\@1.1/1.1.1j/lib/ and duplicating libcrypto.1.1.dylib and renaming to libcrypto.41.dylib fixed the issue (although “lying” about the version may cause problems later).

Then a new error:

ld: library not found for -ltls.15
clang: error: linker command failed with exit code 1 (use -v to see invocation)

find showed no tls library. brew instal tls recommended gnutls, which I have already, 3.6.15:

/usr/local/Cellar/gnutls/3.6.15/lib

Duplicated libgnutls.30.dylib and renamed libtls.15.dylib, and added /usr/local/Cellar/gnutls/3.6.15/lib to the Library Search Path

Then

ld: library not found for -lssl.43

At this point I looked at the build command and saw that it was full of multiple ssl, tls, library options:

Ld /Users/macbook/Library/Developer/Xcode/DerivedData/OpenCV_Course-gnrxushkhmcmvibpfluqortartju/Build/Products/Debug/OpenCV_Course normal x86_64
    cd /Users/macbook/xcode-workspace/OpenCV_Course
    export MACOSX_DEPLOYMENT_TARGET=10.13
    /Users/macbook/Installers/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -arch x86_64 -isysroot /Users/macbook/Installers/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk -L/Users/macbook/Library/Developer/Xcode/DerivedData/OpenCV_Course-gnrxushkhmcmvibpfluqortartju/Build/Products/Debug -L/usr/local/Cellar/opencv/4.5.1_3/lib -L/usr/local/Cellar/openssl@1.1/1.1.1j/lib -L/usr/local/Cellar/gnutls/3.6.15/lib -F/Users/macbook/Library/Developer/Xcode/DerivedData/OpenCV_Course-gnrxushkhmcmvibpfluqortartju/Build/Products/Debug -filelist /Users/macbook/Library/Developer/Xcode/DerivedData/OpenCV_Course-gnrxushkhmcmvibpfluqortartju/Build/Intermediates.noindex/OpenCV_Course.build/Debug/OpenCV_Course.build/Objects-normal/x86_64/OpenCV_Course.LinkFileList -mmacosx-version-min=10.13 -Xlinker -object_path_lto -Xlinker /Users/macbook/Library/Developer/Xcode/DerivedData/OpenCV_Course-gnrxushkhmcmvibpfluqortartju/Build/Intermediates.noindex/OpenCV_Course.build/Debug/OpenCV_Course.build/Objects-normal/x86_64/OpenCV_Course_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -stdlib=libc++ -lcrypto.41 -lauditd.0 -lnetsnmpagent.25 -lopencv_optflow.4.5.1 -lcupsppdc.1 -lecpg.6.5 -lopencv_dnn_superres.4.5.1 -ltailspin -lopencv_core.4.5.1 -lprequelite -lopencv_objdetect.4.5.1 -lipsec.A -lopencv_rapid.4.5.1 -lffi -lopencv_ximgproc.4.5.1 -lgmalloc -lopencv_stitching.4.5.1 -lopencv_mcc.4.5.1 -lopencv_intensity_transform.4.5.1 -ltls.15 -lnetsnmphelpers.25 -lodmodule -lopencv_bgsegm.4.5.1 -lopencv_imgproc.4.5.1 -lopencv_videostab.4.5.1 -lAccountPolicyTranslation -lpam.1 -lnfshared -lbz2.1.0 -lopencv_xfeatures2d.4.5.1 -lIASAuthReboot -lQMIParserDynamic -ltzupdate -lutil -lnetsnmp.15.1.2 -lopencv_viz.4.5.1 -lnetsnmp.25 /usr/lib/PN548_OSX.dylib -lUniversalAccess -lopencv_bioinspired.4.5.1 -lnetworkextension -lopencv_hfs.4.5.1 -lopencv_xobjdetect.4.5.1 -lMaxEnt -ldscsym -lcoretls -lopencv_calib3d.4.5.1 -lpcreposix.0 -lopencv_features2d.4.5.1 -lDHCPServer.A -lcompression -lresolv.9 -lSMC -lnetwork -lXplugin.1 -lboringssl -lform.5.4 -lsandbox.1 -lodfde -lAudioIssueDetector -lz.1 -laprutil-1.0 -lmarisa -lTelephonyUtilDynamic -lpam.2 -lcupscgi.1 -lXSEvent -lcupsimage.2 -lopencv_face.4.5.1 -lopencv_xphoto.4.5.1 -lcoretls_cfhelpers -liconv.2 /usr/lib/PN548_API.dylib -lopencv_datasets.4.5.1 -lcupsmime.1 -lsysmon -lcoreroutine -lopencv_dpm.4.5.1 -lpmenergy -lapr-1.0 -lssl.43 -late -lcurl.4 -lsystemstats -lusrtcp -ldns_services -lopencv_dnn_objdetect.4.5.1 -lOpenScriptingUtil -lopencv_saliency.4.5.1 -lbsm.0 -lruby.2.3.0 -lopencv_ccalib.4.5.1 -lFDR_osx -llangid -lIASUnifiedProgress /usr/lib/PN548_HAL_OSX.dylib -lopencv_text.4.5.1 -lnetsnmpmibs.25 -lopencv_photo.4.5.1 -lopencv_quality.4.5.1 -lScreenReader -lopencv_line_descriptor.4.5.1 -lSystem.B -lmecab.1.0.0 -lnfrestore -lopencv_videoio.4.5.1 -lnetsnmp.5.2.1 -lspindump -lc++abi -lgcc_s.10.5 -lopencv_freetype.4.5.1 -lpanel.5.4 -lcmph -lssl.35 -lopencv_plot.4.5.1 -lxslt.1 -lCRFSuite -lParallelCompression -lauto -lopencv_ml.4.5.1 -lopencv_shape.4.5.1 -liodbcinst.2.1.18 -lopencv_video.4.5.1 -lipconfig -lquit -lopencv_imgcodecs.4.5.1 -lopencv_structured_light.4.5.1 -lpcre.0 -ldz -liodbc.2.1.18 -lopencv_surface_matching.4.5.1 -lopencv_tracking.4.5.1 -lgermantok -lpq.5.6 -lAudioStatistics -lktrace -lmenu.5.4 -lsasl2.2 -lopencv_aruco.4.5.1 -ledit.3 -lapple_nghttp2 -lsqlite3 -lopencv_alphamat.4.5.1 -lopencv_sfm.4.5.1 -lapple_crypto -lcups.2 -lpmsample -lpgtypes.3.4 -lopencv_highgui.4.5.1 -lDiagnosticMessagesClient -lcrypto.0.9.8 -lcsfde -lhunspell-1.2.0.0.0 -lcharset.1 -lopencv_reg.4.5.1 -ltls.6 -lopencv_phase_unwrapping.4.5.1 -lopencv_img_hash.4.5.1 -lThaiTokenizer -lopencv_stereo.4.5.1 -lopencv_dnn.4.5.1 -lopencv_gapi.4.5.1 -lncurses.5.4 -lsysdiagnose -lATCommandStudioDynamic -lxcselect -lobjc.A -lxar.1 -licucore.A -lBSDPClient.A -leasyperf -lexpat.1 -lAppletTranslationLibrary -lexslt.0 -larchive.2 -lstdc++.6.0.9 -lmecabra -lnetsnmptrapd.25 -lssl.0.9.7 -lheimdal-asn1 /usr/lib/ssh-keychain.dylib -lopencv_rgbd.4.5.1 -lopencv_fuzzy.4.5.1 -lxml2.2 -lopencv_superres.4.5.1 -lopencv_flann.4.5.1 -lMatch.1 -lc++.1 -ltidy.A -llzma.5 -lssl.0.9.8 -lChineseTokenizer -ldtrace -lenergytrace -lFosl_dynamic -lecpg_compat.3.5 -lcrypto.0.9.7 -lpcap.A -lcrypto.35 -lCoreStorage -Xlinker -dependency_info -Xlinker /Users/macbook/Library/Developer/Xcode/DerivedData/OpenCV_Course-gnrxushkhmcmvibpfluqortartju/Build/Intermediates.noindex/OpenCV_Course.build/Debug/OpenCV_Course.build/Objects-normal/x86_64/OpenCV_Course_dependency_info.dat -o /Users/macbook/Library/Developer/Xcode/DerivedData/OpenCV_Course-gnrxushkhmcmvibpfluqortartju/Build/Products/Debug/OpenCV_Course

How is this list generated, and how to edit it (in order to remove annoying dependancies)?

The answer is in Build Phase tab>Link Binary with libraries. Here all of the libraries that are linked to are listed. You can set them to required or optional. Setting to optional didn’t remove the error. You can not remove them from the list in the Build Phase tab.

Ironically, if you right click each of the libraries that ld complains about, and select Show in Finder, they can be seen in /usr/lib. However, adding /usr/lib to the Library Search Path didn’t help. It isn’t clear why these libraries are being used.

To remove a library, you have to go to the Project Navigator pane, and there you can right click them and select Delete. Then chose Remove Reference, not Move to Trash).

Note that for some reason I had seemingly every library in my left hand pane, not only the opencv libraries that I had added.

Solution

In the end I removed all of the libcryto*, libssl* and libtls* entries (there were a number of different versions) in the project navigator pane (down the left hand side), recompiled and it worked. Note that I didn’t have to remove any other libraries, so it is not clear why only “crypto” related libraries had to be removed.

Note: I also removed/deleted the fake duplicate renamed libraries, removed their corresponding path entries in Library Search Path, as well as /usr/bin in the Library Search Path, leaving only the $(inherited) and the  /usr/local/Cellar/opencv/4.5.1_3/lib entry.

Notes for mac

From this comment

I am working on Xcode and I was getting error in “imshow”, in webcam code and for those who are facing the same issue try:  brew install imagesnap , now it’s working perfectly.

From this comment

for Xcode, target -> hardened runtime -> resources -> camera for the camera to work in your app

 

Chapter 1 – Read images, videos and webcams

Time: 22:06

First example is the same as the testcode

Namespaces

Instead of typing

std::string path = "Resources/test.png";
Mat image = cv::imread(path)

we use namespaces:

using namespace std;
using namespace cv;

string path = "Resources/test.png";
Mat image = imread(path)

 

Datatype Mat is an opencv matrix for images.

Time: 29:00

For video (which is a series of images) you have to iterate through t he video  frames and capture each image – us ing while

 

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

////// Images //////
int main() {
    string path = "Resources/test.png";
    Mat image = imread(path);
    imshow("Image", image);
    waitKey(0);
    return (0);
}

////// Video //////
int main() {
    string path = "Resources/test_video.mp4"; 
    VideoCapture cap(path);
    Mat image;
    while (true) {
        cap.read(image);
        imshow("Image", image);
//      waitKey(1);  // Very fast video playback 
        waitKey(20); // Very fast video playback
     }
    return (0);
}

////// Webcam //////
int main() {
    VideoCapture cap(0);
    Mat image;
    while (true) {
        cap.read(image);
        imshow("Image", img);
        waitKey(1);  // Very fast video playback 
    }
    return (0);
}

Chapter 2 – Basic preprocessing functions

Time:36:00

Only one file with main() in it, so either:

  • comment out, or
  • exclude (XCode = Uncheck Target Membership)

 

Chapter 3 – Resize and Crop

 

scale as well as specific size

 

region of interest for crop, Rect data type

 

Chapter 4 – Text and shapes

Time 58:31

Creating a blank image

Circle

1:04:49 Rectangle Can use:

  • Rect or
  • can define two points

Chapter 5 – Warp

1:11:10

The format code, command A, ctrl I

 

Floating points required, Point2f

 

2.5″ x  3.5″ – keep the same aspect ratio

transformation matrix

 

Chapter 6 – Colour Detection

Time: 1:22:40

convert to HSV – as it is easier to find the colour

use inrange to collect the colour

the colour is not just one colour, it is a range of colours

Trackbars

Time: 1:30;00

use while loop

hmax is 179 and not 255

vmax and satmax are 255

hmin,smin and vmin are 0

Again, the trackbars don’t work correctly (on OSX ?). Known Issue: 5056

 

Chapter 7 – Shape/Contour detection

1:37:18

Preprocess before finding shapes:

  • find edges, and contours, and then we know what shape
  • Use canny edge detector to find edges, then find contour points

Use dilate to close any gaps in the contour

 

create function getContours()

 

contours is a vector, a list, and inside a list of point – a vector of vectors. Each vector is a contour, each contour has some points

{{Point(20,30), Point(50,60)},{},{}}
vector<vector<Point>>

hierarchy, vector with four integers inside => vector<Vec4i>

1:50:10 Contours found demo

There are two versions of findContours with differing number of arguments, xcode doesn’t auto detect which is being used. You must select the function with  the correct number of arguments first, else it gives an error…. Pathetic!!!!!

1:50:44 – Find area and filter small areas – to remove noise, i.e. the blotch on shapes.png.

if area is above a certain threshold then it is a shape and not noise.

 

1:54:54 – Find bounding box

perimeter

Find number of points, 4 – rectangle, 3 triangle, a lot then it is a circle. Need new array to hold the values

Instead of  0.02*perimeter you can use 3, or 5

true for closed

contourPoly is exactly the same as contours, but has a subset of the points (the corner points) , not all of the points. we know the size can not exceed the number of contours, so we can define its size. We can only define the size after the contours have been found, i.e. after findContours, and hence the size of contours is known.

1:59:52 check length of contourpoly, to find the number of corners, will give approx of shape

 

2:01:10 Find bounding box

rectangle has two methods for leftTop and right Bottom points

2:05:00 Determine which shape is which

2:10:37 differentiate square from rect

Chapter 8 – Face detection

Time: 2:14:52

Viola Johns method of Haarcascade

To detect the faces and store them we need the bounding boxes, so create a vector of rectangles

    faceCascade.detectMultiScale(image, faces, 1.1, 10);

scale factor, minimum neighbours

Project 1 – Virtual Paint

Time: 2:22:22

Have array of min and max values of all colours, loop through array/matrix/vector and one by one find an image for that. So we”l  have multiple masks, one for green one for yellow, one for every colour detected

vector of vector of ints

{{},{},{}} 
vector<vector<Point>>

ColourPicker script: code is the same as chapter 6 but with a webcam

2:39:00 Demo run for pen masks.

I got a run-time crash:

libc++abi.dylib: terminating with uncaught exception of type cv::Exception: OpenCV(4.5.1) /tmp/opencv-20210302-80059-1ewoogj/opencv-4.5.1/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'

which magically disappeared a few hours later. Possibly due to no image from the camera?

See this answer to  Xcode: View Console History After Cleared?

Add another colour, easy: Add HSV and BGR values to the respective vectors (lists). Can also add an additional vector for the names of the colours (to be used as the mask window titles)

Time: 2:42:00 Now, from the mask, we need to find the points where we want to draw, i.e. the tip of the pen. So we need the contours of the masks.

Use getContours() from chapter 7, and modify

Instead of passing second output image as a parameter, a global is used instead – this is not a good idea.

Easier to get the tip of the marker from the bounding box, rather than getting it from the contour

2:50:00 return the point

Another global variable, point of pen, but it is not points, but

vector<vector<int>>

like this

{{x, y, colourID},{x, y, colourID},...}

append using .push_back

Need to check for zero, if nothing is detected, and only append if

 

2:54:34 now paint the points (please kill me now, so fucking boring!!!)

When creating drawOnCanvas(), the globals are used as function arguments… what is the point of that????!!!! Jesus, this is pathetic.

Further work

  • Instead of dots, draw lines
  • Erase method

Project 2 – Document Scanner

Time: 3:02;53

Process

  • find edge,
  • know where paper is,
  • from the co-ords, extract the four corners,
  • then warp image, to get a top view..
    // Preprocessing
    // Contours - get biggest
    // Warp

Scale the image down temporarily, for display purposes only. When project is finished the scaling should be removed, so that a high quality image is worked with.

More globals used – this is so that they can be displayed at the end

Copy image

Note: How to do the equivalent to the Python command image.copy() in C++, in order to make a backup image? .copy() comes from numpy. From Copy Mat in opencv, you use .clone() , which is a property  of Mat, instead.

Or, see this answer to Create blank image in OpenCV C++:

image.copyTo(lena1);

blah

Preprocessing

Time: 3:06:05 – Preprocessing

Note: how to make imageBlank?

Get Contours

Time: 3:10:32

Use the one parameter getContours() from project 1, and modify slightly

3:11:30

  • Need contours
  • filtration by area
  • Need approximation – for four points
  • Return a vector of the corner points of the biggest contour
  • Do not need the bounding rectangle, nor its points, nor its draw

Find the points of the biggest contour

3:13:29

To determine which is the sheet of paper, we need to find contour with the maxArea, but only if it is a rectangle

Standard corner points order

3:22:23

sum and difference, max and min.

vector of int which are the sums of the x and y points

(25,45)     68
(400,30)    430
(350,400)   750
(25,300)    325

{68, 430, 750, 325}

push_back, min_element, max_element

    reorderedCornerPoints.push_back(unorderedPoints[min_element(sumPoints.begin(), sumPoints.end()) - sumPoints.begin()]); // [0]
    reorderedCornerPoints.push_back(unorderedPoints[max_element(diffPoints.begin(), diffPoints.end()) - diffPoints.begin()]); // [1]
    reorderedCornerPoints.push_back(unorderedPoints[min_element(diffPoints.begin(), diffPoints.end()) - diffPoints.begin()]); // [2]
    reorderedCornerPoints.push_back(unorderedPoints[max_element(sumPoints.begin(), sumPoints.end()) - sumPoints.begin()]); // [3]

 

Warp image

3:36:06

width and height of A4 paper is small, so we multiply by 2, and use as pixels

Copy code from chapter 5

Crop

3:41:33

Crop using a Rect.

Crop 5 pixels from all sides


Further work: Add a webcam

Project 3 – Number plate

Time: 3:46:16

Based on Chapter 8 – Haarcascade

and chapter 1 webcam

Changing face to plates

Time: 3:49:05

Crop

Time 3:51:35

Crop using the Rect of the current plate

Save the cropped plate

Time: 3:53:41

Test plates:  Deciphering-number-plates-russia/, Russian-recall-of-lucky-thief-license-plates-following-disruptive-popularity-a50175 (image),  https://ifworlddesignguide.com/entry/236101-russian-license-plates

XCode Usage Note

This answer to What do the “M” and “A” icons in the Project Navigator of Xcode 4 mean when I create a new project?: Github source control:

  • ? – Unversioned
  • M – Modified
  • A – Added
  • A+ – Moved / renamed
  • U – Newer version of a file on source control
  • I – Item is being ignored (e.g. with the svn:ignore property).
  • ! – Item is missing (e.g. you moved or deleted it without using svn). This also indicates that a directory is incomplete (a checkout or update was interrupted).

How to increase font size in the Xcode editor? – command key plus plus

HOw to format code:

Xcode source automatic formatting: Cmd A and Ctrl I

XCode < 8: https://github.com/benoitsan/BBUncrustifyPlugin-Xcode

Xcode 8 banned plugins: https://github.com/theswiftdev/awesome-xcode-extensions

Notes on getContours()

There are three versions of getContours():

  1. Chapter 7 – take two arguments
  2. VirtualPaint – Returns Point of pentip, take one argument (the other is global), although I made a two argument version. Rename to get pentipPoint()?
  3. DocumentScanner – Returns vector of the corner points, takes one argument, the other is global. Rename to getCornerPoints()?

StackImages

How to emulate the stackImages() used in Python:

Show multiple (2,3,4,…) images in the same window in OpenCV

DisplayManyImages  – but DisplayManyImages() requires that the number of images is passed as an argument. It is better to determine this dynamically.

This answer seems simplest:

Mat a, Mat b, Mat dst // a,b loaded

cv::hconcat(a, b, dst) // horizontal
cv::vconcat(a, b, dst) // vertical

so that then Mat dst -> | a | b |

or do it with vector:

std::vector matrices = {
            a, b
    };
hconcat(matrices, dst);

The images should be passed in a vector of vectors of Mat, without the need to specify how many images there are:

vector<vector<Mat>>

{{image, imageGrey, imageBlur},{imageCanny, imageDilate, imageWarp}...}

Images should be resized, but not stretched. Overload for Scale, and Labels

See hconcat and vconcat for passing an array of arrays.

Blank image

Need a blank Image, same size as another image, to use as a filler? See this answer to Create blank image in OpenCV C++

Mat imageBlank = Mat::zeros(Size(image.cols,image.rows),CV_8UC1);

Conundrum 1

How to pass blank image to stackImages()? Well, there is no worry, as the blank can be declared in main() and passed as like other images, or there is no need, the function can either:

  • return an error, if filler images are not supplied, or;
  • return its own blank image (maybe a reference is required?)
  • create its own blank image filler.

Conundrum 2

How to pass either a vector of vectors of Mat or just a (single) vector of Mat? Function definition needs to know which =- otherwise two separate functions are required, one for single row and one for multiple rows each with different definitions…

See Passing vector of vectors to function – although not a solution.

The solution is simple:

  • Declare function argument as a vector of vectors of Mat: vector<vector<Mat>>
  • If you need to pass just a single row, then pass vector of single vector of Mat, not a vector of Mat, for example: {{imageCanny, imageDilate, imageErode}}, not
    {imageCanny, imageDilate, imageErode} – note the double braces.
  • Obviously a vector of vectors of Mat, {{imageCanny, imageDilate, imageErode},{imageCanny, imageDilate, imageErode}} will also work, using this method.

Conundrum 3

Differing image depths causes a crash. Solution, convert greyscale to BGR:

        for (int i=0; i<nCols;i++){  // check for greyscale
            if (images[i].channels() == 1){
                cvtColor(images[i], images[i], COLOR_GRAY2BGR);
            }
        }

Further Work

Create/replicate Python-like functionality:

  • Read multiple files from directory, so as to be able to add and read additional files without needing to specify them. like os.ListDir() in Python. I can’t remember why I want to do this, what for?
  • stackImages(), stackScaledImages() and stackImagesWithLabels() – overload the function name.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s