diff --git a/.gitignore b/.gitignore
index f652b45..7b6eba3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -297,3 +297,36 @@ __pycache__/
*.btm.cs
*.odx.cs
*.xsd.cs
+
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
\ No newline at end of file
diff --git a/AdvancedVision/AdvancedVision.sln b/AdvancedVision/AdvancedVision.sln
new file mode 100644
index 0000000..32d916b
--- /dev/null
+++ b/AdvancedVision/AdvancedVision.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvancedVision", "AdvancedVision.vcxproj", "{D07114EF-4EC2-45EE-944D-5A269C142C0F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D07114EF-4EC2-45EE-944D-5A269C142C0F}.Debug|x64.ActiveCfg = Debug|x64
+ {D07114EF-4EC2-45EE-944D-5A269C142C0F}.Debug|x64.Build.0 = Debug|x64
+ {D07114EF-4EC2-45EE-944D-5A269C142C0F}.Debug|x86.ActiveCfg = Debug|Win32
+ {D07114EF-4EC2-45EE-944D-5A269C142C0F}.Debug|x86.Build.0 = Debug|Win32
+ {D07114EF-4EC2-45EE-944D-5A269C142C0F}.Release|x64.ActiveCfg = Release|x64
+ {D07114EF-4EC2-45EE-944D-5A269C142C0F}.Release|x64.Build.0 = Release|x64
+ {D07114EF-4EC2-45EE-944D-5A269C142C0F}.Release|x86.ActiveCfg = Release|Win32
+ {D07114EF-4EC2-45EE-944D-5A269C142C0F}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {718B94D4-63F0-4DFC-84A7-C7CA7AF5ACA9}
+ EndGlobalSection
+EndGlobal
diff --git a/AdvancedVision/AdvancedVision.vcxproj b/AdvancedVision/AdvancedVision.vcxproj
new file mode 100644
index 0000000..1447682
--- /dev/null
+++ b/AdvancedVision/AdvancedVision.vcxproj
@@ -0,0 +1,175 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {d07114ef-4ec2-45ee-944d-5a269c142c0f}
+ Win32Proj
+ AdvancedVision
+ 10.0.15063.0
+
+
+
+ Application
+ true
+ v141
+ Unicode
+
+
+ Application
+ false
+ v141
+ true
+ Unicode
+
+
+ Application
+ true
+ v141
+ Unicode
+
+
+ Application
+ false
+ v141
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ C:\opencv\build\include;%(AdditionalIncludeDirectories)
+ C:\opencv\build\include;%(AdditionalUsingDirectories)
+
+
+ Console
+ true
+ C:\opencv\build\x64\vc14\lib;%(AdditionalLibraryDirectories)
+ opencv_world330.lib;opencv_world330d.lib;%(AdditionalDependencies)
+
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ C:\opencv\build\include;%(AdditionalIncludeDirectories)
+ C:\opencv\build\include;%(AdditionalUsingDirectories)
+
+
+ Console
+ true
+ C:\opencv\build\x64\vc14\lib;%(AdditionalLibraryDirectories)
+ opencv_world330.lib;opencv_world330d.lib;%(AdditionalDependencies)
+
+
+
+
+ NotUsing
+ Level3
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ C:\opencv\build\include;%(AdditionalIncludeDirectories)
+ C:\opencv\build\include;%(AdditionalUsingDirectories)
+
+
+ Console
+ true
+ true
+ true
+ opencv_world330.lib;opencv_world330d.lib;%(AdditionalDependencies)
+ C:\opencv\build\x64\vc14\lib;%(AdditionalLibraryDirectories)
+
+
+
+
+ NotUsing
+ Level3
+ MaxSpeed
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ C:\opencv\build\include;%(AdditionalIncludeDirectories)
+ C:\opencv\build\include;%(AdditionalUsingDirectories)
+
+
+ Console
+ true
+ true
+ true
+ opencv_world330.lib;opencv_world330d.lib;%(AdditionalDependencies)
+ C:\opencv\build\x64\vc14\lib;%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AdvancedVision/AdvancedVision.vcxproj.filters b/AdvancedVision/AdvancedVision.vcxproj.filters
new file mode 100644
index 0000000..168e7c1
--- /dev/null
+++ b/AdvancedVision/AdvancedVision.vcxproj.filters
@@ -0,0 +1,36 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/AdvancedVision/ReadMe.txt b/AdvancedVision/ReadMe.txt
new file mode 100644
index 0000000..686284f
--- /dev/null
+++ b/AdvancedVision/ReadMe.txt
@@ -0,0 +1,37 @@
+========================================================================
+ CONSOLE APPLICATION : [!output PROJECT_NAME] Project Overview
+========================================================================
+
+AppWizard has created this [!output PROJECT_NAME] application for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your [!output PROJECT_NAME] application.
+
+
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+ This is the filters file for VC++ projects generated using an Application Wizard.
+ It contains information about the association between the files in your project
+ and the filters. This association is used in the IDE to show grouping of files with
+ similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+ "Source Files" filter).
+
+ This is the main application source file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named [!output PROJECT_NAME].pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/AdvancedVision/Source.cpp b/AdvancedVision/Source.cpp
new file mode 100644
index 0000000..3e051f8
--- /dev/null
+++ b/AdvancedVision/Source.cpp
@@ -0,0 +1,33 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace cv;
+using namespace std;
+
+int main(int argc, char** argv)
+{
+ Mat image = imread("input/Week2/basisfiguren.jpg", CV_LOAD_IMAGE_COLOR);
+ if (!image.data)
+ {
+ cout << "Could not open or find the image" << std::endl;
+ return -1;
+ }
+
+ Mat gray_image;
+ cvtColor(image, gray_image, CV_BGR2GRAY);
+
+ imshow("Source", image);
+ imshow("Gray image", gray_image);
+
+ waitKey(0);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/AdvancedVision/allContoursTestprogramma.cpp b/AdvancedVision/allContoursTestprogramma.cpp
new file mode 100644
index 0000000..99f34c0
--- /dev/null
+++ b/AdvancedVision/allContoursTestprogramma.cpp
@@ -0,0 +1,106 @@
+// Functionaliteit: Testprogramma voor het testen van de allContours() functie
+// Zie module Vision C++ voor Gevorderden Opdracht 2 van Fase 1
+// De demo laat met avansvisionlib en OpenCV de contouren zien.
+//
+// De algoritmiek wordt in de eerste workshop toegelicht.
+//
+// Jan Oostindie, dd 8-11-2016
+//
+#include "opencv2/imgproc/imgproc.hpp"
+#include "opencv2/highgui/highgui.hpp"
+#include
+#include
+#include "avansvisionlib.h"
+
+using namespace cv;
+using namespace std;
+
+
+int main(int argc, char *argv[])
+{
+ // zie: project properties - configuration properties - debugging - command arguments
+ if (argc != 2)
+ {
+ cout << "NB! Geef als command argument volledige padnaam van de imagefile mee" << endl;
+ return -1;
+ }
+ else cout << "De imagefile = " << argv[1] << endl;
+
+ // Lees de afbeelding in
+ Mat image;
+ image = imread(argv[1], CV_LOAD_IMAGE_COLOR);
+ if (!image.data)
+ {
+ cout << "Could not open or find the image" << std::endl;
+ return -1;
+ }
+
+ // De afbeelding converteren naar een grijswaarde afbeelding
+ Mat gray_image;
+ cvtColor(image, gray_image, CV_BGR2GRAY);
+
+ // Converteren naar grijswaarde afbeelding
+ cout << "Imagefile: " << argv[1] << " met succes geconverteerd naar grijswaarde beeld." << endl;
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ imshow("Original", gray_image);
+ waitKey(0);
+
+ /** ! Gebruik een region of interest voor de rummikub images **/
+ // Mat imageROI = gray_image(Rect(34, 28, 976, 82));
+ // imshow("imageROI", imageROI);
+ // waitKey(0);
+
+ // Grijswaarde afbeelding thresholden
+ Mat binaryImage;
+
+ /** ! Gebruik een region of interest voor de rummikub figuren **/
+ // threshold(imageROI, binaryImage, 65, 1, CV_THRESH_BINARY_INV);
+
+ // Stel een threshold in. Laad evt de figuur eerst in VisionLab om een goede
+ // threshold te bepalen.
+ // ! Comment this line out when using rummikub images
+ threshold(gray_image, binaryImage, 165, 1, CV_THRESH_BINARY_INV);
+
+ // Alvorens bewerkingen uit te voeren op het beeld converteren we deze
+ // naar een Mat object met grotere diepte (depth), t.w. 16 bits signed
+ Mat binary16S;
+ binaryImage.convertTo(binary16S, CV_16S);
+
+ show16SImageStretch(binary16S,"Binary image");
+
+ // haal de contouren uit het binary image
+ vector> contours;
+ cout << "Contouren bepalen...";
+ int aantal = allContours(binary16S, contours); // <<<<*** De opdracht is dus om deze functie te maken ***
+
+ // druk alle punten van alle gevonden contouren af
+ string line;
+ cout << "Aantal gevonden contouren = " << contours.size() << endl;
+ getline(cin, line);
+ for (int i = 0; i < contours.size(); i++) {
+ cout << "*** Contour " << i + 1 << " ***" << endl;
+ cout << "Press ENTER to continue....";
+ getline(cin, line);
+ for (int j = 0; j < contours[i].size(); j++) {
+ cout << "(" << contours[i][j].x << "," << contours[i][j].y << ")" << endl;
+ }
+ }
+
+ // Creeer een witte image
+ Mat contourImage = cvCreateImage(cvSize(binary16S.cols, binary16S.rows), IPL_DEPTH_8U, 3);
+ contourImage = Scalar(255, 255, 255);
+
+ // teken de contouren op de witte image
+ drawContours(contourImage, contours, -1, CV_RGB(255, 0, 0));
+
+ // druk het image met de contouren af
+ imshow("Found contours", contourImage);
+ waitKey(0);
+
+ string pipo;
+ cin >> pipo;
+
+ return 0;
+}
diff --git a/AdvancedVision/avansvisionlib.cpp b/AdvancedVision/avansvisionlib.cpp
new file mode 100644
index 0000000..79ca0b1
--- /dev/null
+++ b/AdvancedVision/avansvisionlib.cpp
@@ -0,0 +1,763 @@
+// avansvisionlib - Growing Visionlibrary of Avans based on OpenCV 2.4.10
+// Goal: deep understanding of vision algorithms by means of developing own (new) algorithms.
+//
+// Copyright Jan Oostindie, basic version 1.0 dd 8-11-2016. Contains basic functions to perform calculations on matrices/images of class Mat.
+// Including BLOB labeling functions
+//
+// Note: Students of Avans are free to use this library in projects and for own vision competence development. Others may ask permission to use it by means
+// of sending an email to Jan Oostindie, i.e. jac.oostindie@avans.nl
+
+#include "avansvisionlib.h"
+#include
+#include /* srand, rand */
+#include /* time */
+
+// pre: (i < m.rows) & (j < m.cols)
+// Mat is call by reference
+void setEntry(Mat m, int i, int j, double value) {
+ int index = i * m.cols + j;
+ double * p = m.ptr(0);
+ p[index] = value;
+} // setEntry
+
+// pre: (i < m.rows) & (j < m.cols)
+double getEntry(Mat m, int i, int j) {
+ int index = i * m.cols + j;
+ double * p = m.ptr(0);
+ return *(p + index);
+} // getEntry
+
+
+// func: calculate product of a row and column of equal length
+// pre: (row.cols == col.rows)
+double inproduct(Mat row, Mat col) {
+ double * p1 = row.ptr(0);
+ double * p2 = col.ptr(0);
+ double sumproducts = 0;
+ for (int i = 0; i < row.cols; i++)
+ sumproducts += p1[i] * p2[i];
+ return sumproducts;
+} // inproduct
+
+void printMatrix(Mat m) {
+ for (int i = 0; i < m.rows; i++) {
+ for (int j = 0; j < m.cols; j++)
+ cout << getEntry(m, i, j) << " ";
+ cout << endl;
+ }
+ cout << endl;
+} // printMatrix
+
+
+Mat getRow(Mat m, int rowNr) {
+ Mat result = Mat_(1, m.cols);
+ double entry;
+ for (int colNr = 0; colNr < m.cols; colNr++) {
+ entry = getEntry(m, rowNr, colNr);
+ // cout << " ** getRow ** " << endl;
+ // cout << " entry = " << entry << endl;
+ setEntry(result, 0, colNr, entry);
+ }
+ return result;
+} // getRow
+
+Mat getCol(Mat m, int colNr) {
+ Mat result = Mat_(m.rows, 1);
+ double entry;
+ for (int rowNr = 0; rowNr < m.rows; rowNr++) {
+ entry = getEntry(m, rowNr, colNr);
+ // cout << " ** getColumn ** " << endl;
+ // cout << " entry = " << entry << endl;
+ setEntry(result, rowNr, 0, entry);
+ }
+ return result;
+} // getCol
+
+
+
+// pre: (a.cols == b.rows)
+Mat multiply(Mat a, Mat b)
+{
+ Mat result = Mat_(a.rows, b.cols);
+ double inprod;
+ for (int arow = 0; arow < a.rows; arow++) {
+ for (int bcol = 0; bcol < b.cols; bcol++) {
+ inprod = inproduct(getRow(a, arow), getCol(b, bcol));
+ setEntry(result, arow, bcol, inprod);
+ }
+ }
+ return result;
+} // multiply
+
+// pre: matrices have equal dimensions i.e. (a.cols == b.cols) & (a.rows == b.rows)
+Mat add(Mat a, Mat b)
+{
+ Mat result = Mat_(a.rows, a.cols);
+ double entrysum;
+ for (int row = 0; row < a.rows; row++) {
+ for (int col = 0; col < a.cols; col++) {
+ entrysum = getEntry(a, row, col) + getEntry(b, row, col);
+ setEntry(result, row, col, entrysum);
+ }
+ }
+ return result;
+} // add
+
+
+Mat transpose(Mat m) {
+ Mat result = Mat_(m.cols, m.rows);
+ for (int row = 0; row < m.rows; row++)
+ for (int col = 0; col < m.cols; col++)
+ setEntry(result, col, row, getEntry(m, row, col));
+ return result;
+} // transpose
+
+
+// func: sets all entries of a matrix to a value
+// pre: true
+void setValue(Mat m, double value) {
+ for (int row = 0; row < m.rows; row++)
+ for (int col = 0; col < m.cols; col++)
+ setEntry(m, row, col, value);
+} // setValue
+
+
+double generateRandomValue(double min, double max) {
+ int steps = rand() % 100 + 1;
+ double dx = (max - min) / 100;
+ return min + dx * steps;
+} // generateRandomValue
+
+
+// func: sets all entries of a matrix to a random value in interval [min,max]
+// pre: true
+void setRandomValue(Mat m, double min, double max) {
+ srand(time(NULL));
+ for (int row = 0; row < m.rows; row++)
+ for (int col = 0; col < m.cols; col++)
+ setEntry(m, row, col, generateRandomValue(min, max));
+} // randomValue
+
+
+
+/*********************************** Image operaties ****************************************/
+// NB images are supposed to have 1 channel (B/W image) and depth 16 bits signed (CV_16S)
+/********************************************************************************************/
+
+void setEntryImage(Mat m, int i, int j, _int16 value) {
+ int index = i * m.cols + j;
+ _int16 * p = m.ptr<_int16>(0);
+ p[index] = value;
+} // setEntry
+
+// pre: (i < m.rows) & (j < m.cols)
+_int16 getEntryImage(Mat m, int i, int j) {
+ int index = i * m.cols + j;
+ _int16 * p = m.ptr<_int16>(0);
+ return *(p + index);
+} // getEntryImage
+
+// func: calculate product of a row and column of equal length
+// pre: (row.cols == col.rows)
+_int16 inproductImage(Mat row, Mat col) {
+ _int16 * p1 = row.ptr<_int16>(0);
+ _int16 * p2 = col.ptr<_int16>(0);
+ _int16 sumproducts = 0;
+ for (int i = 0; i < row.cols; i++)
+ sumproducts += p1[i] * p2[i];
+ return sumproducts;
+} // inproductImage
+
+
+Mat getRowImage(Mat m, int rowNr) {
+ Mat result = Mat_<_int16>(1, m.cols);
+ _int16 entry;
+ for (int colNr = 0; colNr < m.cols; colNr++) {
+ entry = getEntryImage(m, rowNr, colNr);
+ setEntryImage(result, 0, colNr, entry);
+ }
+ return result;
+} // getRow
+
+Mat getColImage(Mat m, int colNr) {
+ Mat result = Mat_<_int16>(m.rows, 1);
+ _int16 entry;
+ for (int rowNr = 0; rowNr < m.rows; rowNr++) {
+ entry = getEntryImage(m, rowNr, colNr);
+ setEntryImage(result, rowNr, 0, entry);
+ }
+ return result;
+} // getColImage
+
+Mat multiplyImage(Mat a, Mat b)
+{
+ Mat result = Mat_<_int16>(a.rows, b.cols);
+ _int16 inprod;
+ for (int arow = 0; arow < a.rows; arow++) {
+ for (int bcol = 0; bcol < b.cols; bcol++) {
+ inprod = inproductImage(getRow(a, arow), getColImage(b, bcol));
+ setEntry(result, arow, bcol, inprod);
+ }
+ }
+ return result;
+} // multiplyImage
+
+// pre: matrices have equal dimensions i.e. (a.cols == b.cols) & (a.rows == b.rows)
+Mat addImage(Mat a, Mat b)
+{
+ Mat result = Mat_<_int16>(a.rows, a.cols);
+ _int16 entrysum;
+ for (int row = 0; row < a.rows; row++) {
+ for (int col = 0; col < a.cols; col++) {
+ entrysum = getEntryImage(a, row, col) + getEntryImage(b, row, col);
+ setEntryImage(result, row, col, entrysum);
+ }
+ }
+ return result;
+} // addImage
+
+
+// func: searches the maximum pixel value in the image
+// return: maximum pixel
+_int16 maxPixelImage(Mat m) {
+ _int16 max = getEntryImage(m, 0, 0);
+ _int16 next;
+ for (int row = 0; row < m.rows; row++) {
+ for (int col = 0; col < m.cols; col++) {
+ next = getEntryImage(m, row, col);
+ if (next > max) max = next;
+ }
+ }
+ return max;
+} // maxPixelImage
+
+// func: searches the minimum pixel value in the image
+// return: minimum pixel value
+_int16 minPixelImage(Mat m) {
+ _int16 min = getEntryImage(m, 0, 0);
+ _int16 next;
+ for (int row = 0; row < m.rows; row++) {
+ for (int col = 0; col < m.cols; col++) {
+ next = getEntryImage(m, row, col);
+ if (next < min) min = next;
+ }
+ }
+ return min;
+} // minPixelImage
+
+// func: determines the range of the image, i.e. the minimum
+// and maximum pixel value in the image
+// post: range = minPixelValue, maxPixelValue
+void getPixelRangeImage(Mat m, _int16 &minPixelValue, _int16 &maxPixelValue) {
+ _int16 max = getEntryImage(m, 0, 0);
+ _int16 min = getEntryImage(m, 0, 0);
+ _int16 next;
+ for (int row = 0; row < m.rows; row++) {
+ for (int col = 0; col < m.cols; col++) {
+ next = getEntryImage(m, row, col);
+ if (next > max) max = next;
+ else
+ if (next < min) min = next;
+ }
+ }
+ minPixelValue = min;
+ maxPixelValue = max;
+} // getPixelRangeImage
+
+
+// func: stretches the image to a specified range
+void stretchImage(Mat m, _int16 minPixelValue, _int16 maxPixelValue) {
+ _int16 min, max, oldValue, newValue;
+ getPixelRangeImage(m, min, max);
+ double scale = maxPixelValue - minPixelValue;
+ scale /= (max - min);
+ for (int row = 0; row < m.rows; row++) {
+ for (int col = 0; col < m.cols; col++) {
+ oldValue = getEntryImage(m, row, col);
+ newValue = scale * (oldValue - min) + minPixelValue;
+ setEntryImage(m, row, col, newValue);
+ }
+ }
+} // stretchImage
+
+
+// func: shows a 16S image on the screen
+// pre: m is a 16S image (depth 16 bits, signed)
+void show16SImageStretch(Mat m, string windowTitle) {
+ Mat mCopy;
+ m.copyTo(mCopy);
+ stretchImage(mCopy, 0, 255);
+ mCopy.convertTo(mCopy, CV_8U);
+// namedWindow(windowTitle, CV_WINDOW_AUTOSIZE);
+ imshow(windowTitle, mCopy);
+ waitKey(0);
+} // show16SImage
+
+// func: shows a 16S image on the screen. All values clipped to the interval 0-255
+// i.e. value < 0 => 0; 0 <= value <= 255 => value ; value > 255 => 255
+/// pre: m is a 16S image (depth 16 bits, signed)
+void show16SImageClip(Mat m, string windowTitle) {
+ Mat mCopy;
+ m.copyTo(mCopy);
+ mCopy.convertTo(mCopy, CV_8U);
+// namedWindow("show16SImageClip", CV_WINDOW_AUTOSIZE);
+ imshow(windowTitle, mCopy);
+ waitKey(0);
+} // show16SImage
+
+
+// func: histogram gamma correction
+// pre: image has depth 8 bits unsigned and 1 or 3 channels
+// post: entry(i,j) = 255*power(entry@pre(i,j)/255)^gamma
+void gammaCorrection(Mat image, float gamma) {
+ unsigned char lut[256];
+ for (int i = 0; i < 256; i++) {
+ lut[i] = saturate_cast(pow((float)(i / 255.0), gamma) * 255.0f);
+ }
+ // dst = src.clone();
+ const int channels = image.channels();
+ switch (channels) {
+ case 1: {
+ MatIterator_ it, end;
+ for (it = image.begin(), end = image.end(); it != end; it++)
+ *it = lut[(*it)];
+ break;
+ }
+ case 3: {
+ MatIterator_ it, end;
+ for (it = image.begin(), end = image.end(); it != end; it++) {
+ (*it)[0] = lut[((*it)[0])];
+ (*it)[1] = lut[((*it)[1])];
+ (*it)[2] = lut[((*it)[2])];
+ }
+ break;
+ }
+ } // switch
+} // gammaCorrection
+
+
+// func: makes a administration used for labeling blobs.
+// the function adds a edge of 1 pixel wide tot a binary image, all with value 0.
+// All 1's are made -1. The result is returned.
+// This function is used by function labelBLOBs
+// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
+// return_matrix: All "1" are made "-1" meaning value 1 and unvisited.
+Mat makeAdmin(Mat binaryImage) {
+ Mat result = Mat_<_int16>(binaryImage.rows+2, binaryImage.cols+2);
+
+ // eerste rij 0 maken
+ for (int col = 0; col < result.cols; col++)
+ setEntryImage(result,0,col,0);
+
+ // binaryImage copieren naar admin waarbij een 1 steeds wordt omgezet naar -1.
+ for (int row = 1; row < (result.rows-1); row++) {
+
+ // 0 vooraan de rij zetten
+ setEntryImage(result,row,0,0);
+
+ // rij binaryImage copieren
+ _int16 value;
+ for (int col = 1; col < result.cols - 1; col++) {
+ value = getEntryImage(binaryImage, row - 1, col - 1);
+ if (value == 1) value = -1;
+ setEntryImage(result, row, col, value);
+ }
+
+ // 0 achteraan de rij zetten
+ setEntryImage(result, row, result.cols - 1, 0);
+ } // for
+
+ // laatste rij 0 maken
+ for (int col = 0; col < result.cols; col++)
+ setEntryImage(result, result.rows-1, col, 0);
+
+ return result;
+} // makeAdmin
+
+
+// func: Searches the next blob after position (row,col) i.e. searches
+// the next -1 in admin
+// post: if return_value == 1 then (row,col) contains the position
+// where the next blob starts.
+// return_value: 1 next blob found ; starting position is (row,col)
+// 0 no blob found ; (row, col) == (-1, -1)
+bool findNextBlob(Mat admin, int & row, int & col) {
+
+ bool found = false;
+
+ // zoeken in de huidige rij
+ for (int currCol = col; (currCol < (admin.cols - 1)) & !found; currCol++)
+ if (getEntryImage(admin, row, currCol) == -1) {
+ found = true;
+ // row unchanged
+ col = currCol;
+ }
+
+ // zoeken vanaf de volgende rij
+ for (int currRow = row+1; (currRow < (admin.rows-1)) &!found; currRow++)
+ for (int currCol = 1; (currCol < (admin.cols-1)) & !found; currCol++)
+ if (getEntryImage(admin, currRow, currCol) == -1) {
+ found = true;
+ row = currRow;
+ col = currCol;
+ }
+
+ if (!found) {
+ row = -1;
+ col = -1;
+ }
+ return found;
+}; // findNextBlob
+
+// func: gets the entry of a neighbour pixel with relative position nr.
+// Definition of relative positions nr:
+// 7 0 1
+// 6 X 2
+// 5 4 3
+_int16 getEntryNeighbour(const Mat & admin , int x, int y, int nr) {
+ switch (nr) {
+ case 0: return getEntryImage(admin, x - 1, y ); break;
+ case 1: return getEntryImage(admin, x - 1, y + 1); break;
+ case 2: return getEntryImage(admin, x , y + 1); break;
+ case 3: return getEntryImage(admin, x + 1, y + 1); break;
+ case 4: return getEntryImage(admin, x + 1, y); break;
+ case 5: return getEntryImage(admin, x + 1, y - 1); break;
+ case 6: return getEntryImage(admin, x, y - 1); break;
+ case 7: return getEntryImage(admin, x - 1, y - 1); break;
+ default: cout << "ERROR getEntryNeighbour " << endl;
+ }
+} // getEntryNeighbour
+
+// func: determines if there are more than 1 adjacent 1's
+bool moreNext1(const Mat & admin, int x, int y) {
+ int cnt1 = 0;
+ bool more = false;
+ for (int nr = 0; (nr <= 7) & !more; nr++)
+ if (getEntryNeighbour(admin, x, y, nr) == -1) {
+ cnt1++;
+ if (cnt1 > 1) more = true;
+ }
+ return more;
+} // moreNext1
+
+// func: searches the first 1 when rotating around the pixel (currX,currY),
+// starting at position 0. Definition of relative positions:
+// 7 0 1
+// 6 X 2
+// 5 4 3
+void findNext1(Mat admin, int & currX, int & currY, int & next1) {
+ int rotX, rotY;
+
+ rotX = currX - 1 ; rotY = currY ; //0
+ if (getEntryImage(admin, rotX, rotY) == -1) next1 = 0;
+ else {
+ rotX = currX - 1; rotY = currY + 1; //1
+ if (getEntryImage(admin, rotX, rotY) == -1) next1 = 1;
+ else {
+ rotX = currX; rotY = currY + 1; //2
+ if (getEntryImage(admin, rotX, rotY) == -1) next1 = 2;
+ else {
+ rotX = currX + 1; rotY = currY + 1; //3
+ if (getEntryImage(admin, rotX, rotY) == -1) next1 = 3;
+ else {
+ rotX = currX + 1; rotY = currY; //4
+ if (getEntryImage(admin, rotX, rotY) == -1) next1 = 4;
+ else {
+ rotX = currX + 1; rotY = currY - 1; //5
+ if (getEntryImage(admin, rotX, rotY) == -1) next1 = 5;
+ else {
+ rotX = currX; rotY = currY - 1; //6
+ if (getEntryImage(admin, rotX, rotY) == -1) next1 = 6;
+ else {
+ rotX = currX - 1; rotY = currY - 1; //7
+ if (getEntryImage(admin, rotX, rotY) == -1) next1 = 7;
+ else next1 = -99;
+ } // 6
+ } // 5
+ } // 4
+ } // 3
+ } // 2
+ } // 1
+ } //0
+ if (next1 >= 0) {
+ currX = rotX;
+ currY = rotY;
+ }
+} // findNext1
+
+
+// func: labels all pixels of one blob which starts at position (row,col) with blobNr.
+// This function is used by function labelBLOB's which labels all blobs.
+// return_value: area of the blob
+// Evaluation: This function uses a iterative algorithm in which a special labeling technique is
+// is used which gives the opportunity to trace all individiual pixels. This makes it
+// possible for example to save only these pixels on disk or to translate the object in
+// in the image.
+// The disadvantagae however is that the algorithm is more complicated an maybe a little bit
+// slower than the recursive variant.
+int labelIter(Mat & admin, int row, int col, int blobNr) {
+ // Every visited pixel is labeled with:
+ // blobNr*10 +
+ //
+ // definition of relative positions
+ // 7 0 1
+ // 6 X 2
+ // 5 4 3
+ //
+ // The first visited pixel, i.e. (row,col), is labeled with:
+ // blobNr * 10 + 8
+
+ int x = row, y = col;
+ setEntryImage(admin, x, y, blobNr*10 + 8);
+
+ int next1 = -999;
+ int area = 1;
+
+ // flag more is set when any entry in the path has two or more
+ // unvisited neighbours because we visit only one at a time.
+ bool allLabeledFlag = true;
+ while (allLabeledFlag) {
+ allLabeledFlag = false;
+ bool pathLabeled = false;
+ while (!pathLabeled) {
+
+ if (!allLabeledFlag) allLabeledFlag = moreNext1(admin, x, y);
+ findNext1(admin, x, y, next1);
+
+ if (next1 >= 0) {
+ setEntryImage(admin, x, y, blobNr*10 + next1);
+ area++;
+ }
+ else {
+ //findprevious
+ switch (getEntryImage(admin, x, y) % 10) {
+ case 0: x += 1; break;
+ case 1: x += 1; y -= 1; break;
+ case 2: y -= 1; break;
+ case 3: x -= 1; y -= 1; break;
+ case 4: x -= 1; break;
+ case 5: x -= 1; y += 1; break;
+ case 6: y += 1; break;
+ case 7: x += 1; y += 1; break;
+ case 8: pathLabeled = true; break; // currIndex should be 0 now
+ default: cout << "Error func labelIter!";
+ } // case
+ } // else
+ } // while
+ } // while (more)
+ return area;
+} // labelIter
+
+
+// func: labels all pixels of one blob which starts at position (topX,topY) with blobNr.
+// During the labeling proces the centre of gravity is calculated.
+// This function is used by function labelBLOBInfo
+// return_value: area of the blob
+// Evaluation: This function uses a iterative algorithm in which a special labeling technique is
+// is used which gives the opportunity to trace all individiual pixels. This makes it
+// possible for example to save only these pixels on disk or to translate the object in
+// in the image.
+// The disadvantagae however is that the algorithm is more complicated an maybe a little bit
+// slower than the recursive variant.
+int labelIterInfo(Mat & admin, int topX, int topY, int blobNr,
+ int & xGravity, int & yGravity) {
+
+ // Every visited pixel is labeled with:
+ // blobNr*10 +
+ //
+ // definition of relative positions
+ // 7 0 1
+ // 6 X 2
+ // 5 4 3
+ //
+ // The first visited pixel, i.e. (row,col), is labeled with:
+ // blobNr * 10 + 8
+
+ xGravity = topX;
+ yGravity = topY;
+ int x = topX, y = topY;
+ setEntryImage(admin, topX, topY, blobNr * 10 + 8);
+
+ int next1 = -999;
+ int area = 1;
+
+ // allLabeledFlag is set when any entry in the path has two or more
+ // unvisited neighbours because we visit only one at a time.
+ // This algorithm good be speeded up by using a stack (future improvement)
+ bool allLabeledFlag = true;
+ while (allLabeledFlag) {
+ allLabeledFlag = false;
+ bool pathLabeled = false;
+ while (!pathLabeled) {
+
+ if (!allLabeledFlag) allLabeledFlag = moreNext1(admin, x, y);
+ findNext1(admin, x, y, next1);
+
+ if (next1 >= 0) {
+ setEntryImage(admin, x, y, blobNr * 10 + next1);
+ area++;
+ xGravity += x;
+ yGravity += y;
+ }
+ else {
+ //findprevious
+ switch (getEntryImage(admin, x, y) % 10) {
+ case 0: x += 1; break;
+ case 1: x += 1; y -= 1; break;
+ case 2: y -= 1; break;
+ case 3: x -= 1; y -= 1; break;
+ case 4: x -= 1; break;
+ case 5: x -= 1; y += 1; break;
+ case 6: y += 1; break;
+ case 7: x += 1; y += 1; break;
+ case 8: pathLabeled = true; break; // currIndex should be 0 now
+ default: cout << "Error func labelIter!";
+ } // case
+ } // else
+ } // while
+ } // while (more)
+ xGravity /= area;
+ yGravity /= area;
+ return area;
+} // labelIterInfo
+
+
+
+// func: labels all pixels of one blob which starts at position (row,col) with blobNr.
+// return_value: area of the blob
+// Evaluation: This function uses a recursive algorithm which has the advantage that it is easy and trasparent.
+// The disadvantagae however is that it claims a lot of spacee on the stack. I.e. every found
+// pixel results in a function call which in case of large blobs causes a stack overflow.
+int labelRecursive(Mat & admin, int row, int col, int blobNr) {
+ int area = 0;
+ // bij waarde -1 is het pixel nog niet bezocht
+ if (getEntryImage(admin, row, col) == -1) {
+ //cout << "(row,col) = " << "(" << row << "," << col << ")" << endl;
+ // pixel labelen met het volgnummer van de blob
+ setEntryImage(admin, row, col, blobNr);
+ area = 1;
+
+ // alle pixels rondom huidige pixel bezoeken
+ // (row-1,col-1) (row-1,col ) (row-1,col+1)
+ // (row ,col-1) (row, col ) (row ,col+1)
+ // (row+1,col-1) (row, col ) (row+1,col+1)
+ area += labelRecursive(admin, row - 1, col, blobNr);
+ area += labelRecursive(admin, row - 1, col + 1, blobNr);
+ area += labelRecursive(admin, row, col + 1, blobNr);
+ area += labelRecursive(admin, row + 1, col + 1, blobNr);
+ area += labelRecursive(admin, row, col, blobNr);
+ area += labelRecursive(admin, row + 1, col - 1, blobNr);
+ area += labelRecursive(admin, row, col - 1, blobNr);
+ area += labelRecursive(admin, row - 1, col - 1, blobNr);
+ }
+ return area;
+} // label
+
+// func: retrieves a labeledImage from the labeling administration
+// pre : admin is contains labeled pixels with neighbour number information.
+// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
+// labeled with the number of the object they belong to.
+void retrieveLabeledImage(const Mat & admin, Mat & labeledImage) {
+ labeledImage = Mat_<_int16>(admin.rows-2,admin.cols-2);
+
+ for (int row = 1; row < admin.rows-1; row++) {
+ for (int col = 1; col < admin.cols-1; col++) {
+ setEntryImage(labeledImage, row-1,col-1,
+ getEntryImage(admin, row, col) / 10);
+ }
+ }
+} // retrieveLabeledImage
+
+
+// func: labeling of all blobs in a binary image
+// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
+// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
+// labeled with the number of the object they belong to.
+// return_value: the total number of objects.
+int labelBLOBs(Mat binaryImage, Mat & labeledImage) {
+
+ // admin contains the administration of the recursive process.
+ // meaning of the entry values:
+ // -1: a "1" which is not visited yet. Changes to 1 when visited.
+ // 0: always a "0"
+ // 1, 2, 3,... : a "1" which is visited and is labeled with the object number.
+ Mat admin = makeAdmin(binaryImage);
+ int row = 1;
+ int col = 1;
+
+ // init volgnummer
+ int blobNr = 0;
+
+ // label alle BLOBs met een volgnummer
+ while ((row > 0) & (row < (admin.rows - 1)) &
+ (col > 0) & (col < (admin.cols - 1)))
+ if (findNextBlob(admin, row, col)) labelIter(admin, row, col, ++blobNr);
+
+ retrieveLabeledImage(admin, labeledImage);
+
+ // laatste volgnummer is gelijk aan het aantal gevonden blobs
+ return blobNr;
+} // labelBLOBs
+
+// func: removes a BLOB from the labeling administration
+// pre: (posx,posy) is the position of the BLOB, blobNr the number
+// of the blob to be removed.
+void removeBLOB(Mat & admin, int blobNr) {
+ _int16 value;
+ for (int row = 1; row < admin.rows-2; row++)
+ for (int col = 1; col < admin.cols-2; col++) {
+ value = getEntryImage(admin, row, col);
+ while (value > 10) value /= 10;
+ if (value == blobNr) setEntryImage(admin, row, col, 0);
+ }
+} // removeBLOB
+
+// func: labeling of all blobs in a binary image with a area in [threhAreaMin,threhAreaMax]. Default
+// threshold is [1,INT_MAX]. Alle gathered data during the labeling proces is returned,
+// i.e. the positions of the firstpixel of each blob, the position of the blobs (i.e. the
+// centres of gravity) and the area's of all blobs.
+// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
+// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
+// labeled with the number of the object they belong to.
+// areaVec: contains all area's of the blobs. The index corresponds to the number
+// of the blobs. Index 0 has no meaning.
+// return_value: the total number of objects.
+int labelBLOBsInfo(Mat binaryImage, Mat & labeledImage,
+ vector & firstpixelVec, vector & posVec,
+ vector & areaVec,
+ int threshAreaMin, int threshAreaMax) {
+
+ // admin contains the administration of the recursive process.
+ // meaning of the entry values:
+ // -1: a "1" which is not visited yet.
+ // 0: always a "0"
+ // 1, 2, 3,... : a "1" which is visited and is labeled with the object number.
+ Mat admin = makeAdmin(binaryImage);
+ int row = 1;
+ int col = 1;
+
+ // init volgnummer
+ int blobNr = 0;
+ int area;
+ int xGravity, yGravity;
+ // label alle BLOBs met een volgnummer
+ while ((row > 0) & (row < (admin.rows - 1)) &
+ (col > 0) & (col < (admin.cols - 1)))
+
+ if (findNextBlob(admin, row, col)) {
+
+ area = labelIterInfo(admin, row, col, ++blobNr, xGravity, yGravity);
+
+ if ((area >= threshAreaMin) & (area <= threshAreaMax)) {
+ firstpixelVec.push_back(new Point2d(row - 1, col - 1));
+ posVec.push_back(new Point2d(xGravity-1, yGravity-1));
+ areaVec.push_back(area);
+ }
+ else removeBLOB(admin, blobNr--);
+ }
+
+ retrieveLabeledImage(admin, labeledImage);
+
+ // laatste volgnummer is gelijk aan het aantal gevonden blobs
+ return blobNr;
+} // labelBLOBsInfo
diff --git a/AdvancedVision/avansvisionlib.h b/AdvancedVision/avansvisionlib.h
new file mode 100644
index 0000000..704376e
--- /dev/null
+++ b/AdvancedVision/avansvisionlib.h
@@ -0,0 +1,233 @@
+// avansvisionlib - Growing Visionlibrary of Avans based on OpenCV 2.4.10
+// Goal: deep understanding of vision algorithms by means of developing own (new) algorithms.
+//
+// Copyright Jan Oostindie, basic version 0.2 dd 15-9-2016. Contains basic functions to perform calculations on matrices/images of class Mat.
+// Including BLOB labeling functions
+//
+// Note: Students of Avans are free to use this library in projects and for own vision competence development. Others may ask permission to use it by means
+// of sending an email to Jan Oostindie, i.e. jac.oostindie@avans.nl
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace cv;
+using namespace std;
+
+// remark: a functioncall with a Mat-object parameter is a call by reference
+
+/*********************** PROTOTYPES of the function library ************************/
+
+// func: setup a specified entry (i,j) of a matrix m with a specific value
+// pre: (i < m.rows) & (j < m.cols)
+void setEntry(Mat m, int i, int j, double value);
+
+// func: get the value of a specified entry (i,j) of a matrix m
+// pre: (i < m.rows) & (j < m.cols)
+// return: == m(i,j)
+double getEntry(Mat m, int i, int j);
+
+// func: calculate product of a row and column of equal length
+// pre: (row.cols == col.rows) & (row.rows == 1) & (col.cols == 1)
+double inproduct(Mat row, Mat col);
+
+// func: prints matrix m in the console
+// pre: true
+void printMatrix(Mat m);
+
+// func: select and get a row of a matrix m. rowNr contains the row number
+// pre: 0 < rowNr < m.rows
+// return: contains the selected row
+Mat getRow(Mat m, int rowNr);
+
+// func: get a column of a matrix m. colNr contains the column number
+// pre: 0 < colNr < m.cols
+// return: contains the selected column
+Mat getCol(Mat m, int colNr);
+
+// func: multiply two matrices a and b
+// pre: (a.cols == b.rows)
+// return: .rows == b.rows & .cols == b.cols
+Mat multiply(Mat a, Mat b);
+
+// pre: matrices have equal dimensions i.e. (a.cols == b.cols) & (a.rows == b.rows)
+// return: (i,j) == a(i,j) + b(i,j) for all (0,0) <= (i,j) < (a.rows,a.cols)
+Mat add(Mat a, Mat b);
+
+// func: transposes a matrix
+// return: (i,j) = m(j,i) & .rows = m.cols & .cols = m.rows
+Mat transpose(Mat m);
+
+// func: sets all entries of a matrix to a certain value
+// pre: true
+void setValue(Mat m, double value);
+
+// func: generates a randomvalue between min and max
+// pre: true
+double generateRandomValue(double min, double max);
+
+
+// func: sets all entries of a matrix to a random value
+// pre: true
+void setRandomValue(Mat m, double min, double max);
+
+
+
+/*********************************** Image operaties ****************************************/
+// NB images are supposed to have 1 channel (B/W image) and depth 16 bits signed (CV_16S)
+/********************************************************************************************/
+
+// func: setup a specified entry (i,j) of a matrix m with a specific value
+// pre: (i < m.rows) & (j < m.cols)
+void setEntryImage(Mat m, int i, int j, _int16 value);
+
+// func: get the value of a specified entry (i,j) of a matrix m
+// pre: (i < m.rows) & (j < m.cols)
+// return: == m(i,j)
+_int16 getEntryImage(Mat m, int i, int j);
+
+// func: calculate product of a row and column of equal length
+// pre: (row.cols == col.rows) & (row.rows == 1) & (col.cols == 1)
+_int16 inproductImage(Mat row, Mat col);
+
+// func: select and get a row of a matrix m. rowNr contains the row number
+// pre: 0 < rowNr < m.rows
+// return: contains the selected row
+Mat getRowImage(Mat m, int rowNr);
+
+// func: get a column of a matrix m. colNr contains the column number
+// pre: 0 < colNr < m.cols
+// return: contains the selected column
+Mat getColImage(Mat m, int colNr);
+
+// func: multiply two matrices a and b
+// pre: (a.cols == b.rows)
+// return: .rows == b.rows & .cols == b.cols
+Mat multiplyImage(Mat a, Mat b);
+
+// pre: matrices have equal dimensions i.e. (a.cols == b.cols) & (a.rows == b.rows)
+// return: (i,j) == a(i,j) + b(i,j) for all (0,0) <= (i,j) < (a.rows,a.cols)
+Mat addImage(Mat a, Mat b);
+
+
+// func: searches the maximum pixel value in the image
+// return: maximum pixel value
+_int16 maxPixelImage(Mat m);
+
+// func: searches the minimum pixel value in the image
+// return: minimum pixel value
+_int16 minPixelImage(Mat m);
+
+// func: determines the range of the image, i.e. the minimum
+// and maximum pixel value in the image
+// post: range = minPixelValue, maxPixelValue
+void getPixelRangeImage(Mat m, _int16 &minPixelValue, _int16 &maxPixelValue);
+
+// func: transform scale the image
+// return: maximum pixel value
+void stretchImage(Mat m, _int16 minPixelValue, _int16 maxPixelValue);
+
+// func: shows a 16S image on the screen. All values mapped on the interval 0-255
+/// pre: m is a 16S image (depth 16 bits, signed)
+void show16SImageStretch(Mat m, string windowTitle = "show16SImageStretch");
+
+
+// func: shows a 16S image on the screen. All values clipped to the interval 0-255
+// i.e. value < 0 => 0; 0 <= value <= 255 => value ; value > 255 => 255
+/// pre: m is a 16S image (depth 16 bits, signed)
+void show16SImageClip(Mat m, string windowTitle = "show16SImageClip");
+
+
+
+// func: histogram gamma correction
+// pre: image has depth 8 bits unsigned and 1 or 3 channels
+// post: entry(i,j) = 255*power(entry@pre(i,j)/255)^gamma
+void gammaCorrection(Mat image, float gamma);
+
+
+// func: makes a administration used for labeling blobs.
+// the function adds a edge of 1 pixel wide tot a binary image, all with value 0.
+// All 1's are made -1. The result is returned.
+// This function is used by function labelBLOBs
+// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
+// return_matrix: All "1" are made "-1" meaning value 1 and unvisited.
+Mat makeAdmin(Mat binaryImage);
+
+
+// func: Searches the next blob after position (row,col)
+// post: if return_value == 1 then (row,col) contains the position
+// where the next blob starts.
+// return_value: true => blob found ; starting position is (row,col)
+// false => no blob found ; (row, col) == (-1, -1)
+bool findNextBlob(Mat admin, int & row, int & col);
+
+
+// func: searches the first 1 when rotating around the pixel (currX,currY),
+// starting at position 0. Definition of relative positions:
+// 7 0 1
+// 6 X 2
+// 5 4 3
+void findNext1(Mat admin, int & currX, int & currY, int & next1);
+
+// func: gets the entry of a neighbour pixel with relative position nr.
+// Definition of relative positions nr:
+// 7 0 1
+// 6 X 2
+// 5 4 3
+_int16 getEntryNeighbour(const Mat & admin, int x, int y, int nr);
+
+
+// func: determines if there are more than 1 adjacent 1's
+bool moreNext1(const Mat & admin, int x, int y);
+
+
+
+// func: labels all pixels of one blob which starts at position (row,col) with blobNr.
+// This function is used by function labelBLOB's which labels all blobs.
+// return_value: area of the blob
+// Evaluation: This function uses a iterative algorithm in which a special labeling technique is
+// is used which gives the opportunity to trace all individiual pixels. This makes it
+// possible for example to save only these pixels on disk or to translate the object in
+// in the image.
+// The disadvantagae however is that the algorithm is more complicated an maybe a little bit
+// slower than the recursive variant.
+int labelIter(Mat & admin, int row, int col, int blobNr);
+
+
+// func: labels all pixels of one blob which starts at position (row,col) with blobNr.
+// return_value: area of the blob
+// Evaluation: This function uses a recursive algorithm which has the advantage that it is easy and trasparent.
+// The disadvantagae however is that it claims a lot of spacee on the stack. I.e. every found
+// pixel results in a function call which in case of large blobs causes a stack overflow.
+int labelRecursive(Mat & admin, int row, int col, int blobNr);
+
+// func: retrieves a labeledImage from the labeling administration
+// pre : admin is contains labeled pixels with neighbour number information.
+// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
+// labeled with the number of the object they belong to.
+void retrieveLabeledImage(const Mat & admin, Mat & labeledImage);
+
+// func: labeling of all blobs in a binary image
+// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
+// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
+// labeled with the number of the object they belong to.
+// return_value: the total number of objects.
+int labelBLOBs(Mat binaryImage, Mat & labeledImage);
+
+
+// func: labeling of all blobs in a binary image with a area in [threshAreaMin,threshAreaMax]. Default
+// threshold is [1,INT_MAX]. Alle gathered data during the labeling proces is returned,
+// i.e. the positions of the firstpixel of each blob, the position of the blobs (i.e. the
+// centres of gravity) and the area's of all blobs.
+// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
+// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
+// labeled with the number of the object they belong to.
+// areaVec: contains all area's of the blobs. The index corresponds to the number
+// of the blobs. Index 0 has no meaning.
+// return_value: the total number of objects.
+int labelBLOBsInfo(Mat binaryImage, Mat & labeledImage,
+ vector & firstpixelVec, vector & posVec,
+ vector & areaVec,
+ int threshAreaMin = 1, int threshAreaMax = INT_MAX);
diff --git a/AdvancedVision/input/Week 2/basisfiguren.jpg b/AdvancedVision/input/Week 2/basisfiguren.jpg
new file mode 100644
index 0000000..8f843a2
Binary files /dev/null and b/AdvancedVision/input/Week 2/basisfiguren.jpg differ
diff --git a/AdvancedVision/input/Week 2/bolenpijl.jpg b/AdvancedVision/input/Week 2/bolenpijl.jpg
new file mode 100644
index 0000000..422b24f
Binary files /dev/null and b/AdvancedVision/input/Week 2/bolenpijl.jpg differ
diff --git a/AdvancedVision/input/Week 2/monsters.jpg b/AdvancedVision/input/Week 2/monsters.jpg
new file mode 100644
index 0000000..3013a3f
Binary files /dev/null and b/AdvancedVision/input/Week 2/monsters.jpg differ
diff --git a/AdvancedVision/input/Week 2/rummikub.JPG b/AdvancedVision/input/Week 2/rummikub.JPG
new file mode 100644
index 0000000..5b7cca7
Binary files /dev/null and b/AdvancedVision/input/Week 2/rummikub.JPG differ
diff --git a/AdvancedVision/input/Week 2/rummikub0.jpg b/AdvancedVision/input/Week 2/rummikub0.jpg
new file mode 100644
index 0000000..c329e4c
Binary files /dev/null and b/AdvancedVision/input/Week 2/rummikub0.jpg differ