Lecture 10 – Image Processing with OpenCV JJCAO

Slides:



Advertisements
Similar presentations
Chapter Two: Core Module. The Core Functionality Xinwen Fu
Advertisements

Managing Memory Static and Dynamic Memory Type Casts Allocating Arrays of Dynamic Size Resizing Block of Memory Returning Memory from a Function Avoiding.
Computer Science 1620 Variables and Memory. Review Examples: write a program that calculates and displays the average of the numbers 45, 69, and 106.
1 Homework Turn in HW2 at start of next class. Starting Chapter 2 K&R. Read ahead. HW3 is on line. –Due: class 9, but a lot to do! –You may want to get.
Gavin S Page OpenCV Tutorial Part IV A Brief Guide to Memory Management (and other Miscellaneous Functions) 02 December 2005.
Pointers and dynamic objects COMP171 Fall Pointers and dynamic objects/ Slide 2 Topics * Pointers n Memory addresses n Declaration n Dereferencing.
Object Oriented Programming.  OOP Basic Principles  C++ Classes  September 2004  John Edgar 22.
 2003 Prentice Hall, Inc. All rights reserved. 1 Arrays –Structures of related data items –Static entity (same size throughout program) A few types –Pointer-based.
ARRAYS AND POINTERS Although pointer types are not integer types, some integer arithmetic operators can be applied to pointers. The affect of this arithmetic.
C++ for Engineers and Scientists Third Edition
Lesson 7 Arrays CS 1 Lesson 7 -- John Cole1. Arrays Hold Multiple Values Array: variable that can store multiple values of the same type Values are stored.
Introduction to Array The fundamental unit of data in any MATLAB program is the array. 1. An array is a collection of data values organized into rows and.
C++ Functions. 2 Agenda What is a function? What is a function? Types of C++ functions: Types of C++ functions: Standard functions Standard functions.
L.
Differences between C# and C++ Dr. Catherine Stringfellow Dr. Stewart Carpenter.
OpenCV Open source C omputer V ision library By: Bahare Torkaman Fall 2010.
OPENCV TUTORIAL OpenCV Windows 7 Microsoft Visual C++ Express 2010.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 19 Clicker Questions November 3, 2009.
Chapter 7: Arrays. In this chapter, you will learn about: One-dimensional arrays Array initialization Declaring and processing two-dimensional arrays.
Computing IV Visual C Introduction with OpenCV Example Xinwen Fu.
Operator Precedence First the contents of all parentheses are evaluated beginning with the innermost set of parenthesis. Second all multiplications, divisions,
Copyright © 2012 Pearson Education, Inc. Chapter 8 Two Dimensional Arrays.
Addison Wesley is an imprint of © 2010 Pearson Addison-Wesley. All rights reserved. Chapter 5 Working with Images Starting Out with Games & Graphics in.
CS 114 – Class 02 Topics  Computer programs  Using the compiler Assignments  Read pages for Thursday.  We will go to the lab on Thursday.
Introduction to STL and the vector container class CS342 Data Structures Based on Ford & Topp.
L. Akshay Masare Piyush Awasthi IMAGE PROCESSING AND OPENCV.
1 C - Memory Simple Types Arrays Pointers Pointer to Pointer Multi-dimensional Arrays Dynamic Memory Allocation.
1 Programs Composed of Several Functions Syntax Templates Legal C++ Identifiers Assigning Values to Variables Declaring Named Constants String Concatenation.
Computer Science and Software Engineering University of Wisconsin - Platteville 2. Pointer Yan Shi CS/SE2630 Lecture Notes.
CSC 107 – Programming For Science. Announcements  Memorization is not important, but…  … you will all still be responsible for information  Instead.
Introduction of OpenCV Alireza Shirani Researcher of Medical Image and Signal Processing M. S Electrical Engineering yahoo. com Spring.
Copyright  Hannu Laine C++-programming Part 1 Hannu Laine.
Pointers OVERVIEW.
CPS120: Introduction to Computer Science Operations Lecture 9.
C++ for Engineers and Scientists Second Edition Chapter 11 Arrays.
Object-Oriented Programming in C++
Current Assignments Start Reading Chapter 6 Project 3 – Due Thursday, July 24 Contact List Program Homework 6 – Due Sunday, July 20 First part easy true/false.
Chapter 0 Getting Started. Objectives Understand the basic structure of a C++ program including: – Comments – Preprocessor instructions – Main function.
Looping and Counting Lecture 3 Hartmut Kaiser
CS 376b Introduction to Computer Vision 01 / 23 / 2008 Instructor: Michael Eckmann.
CPSC 252 The Big Three Page 1 The “Big Three” Every class that has data members pointing to dynamically allocated memory must implement these three methods:
Two-Dimensional Arrays ELEC 206 Computer Applications for Electrical Engineers Dr. Ron Hayne.
Object Management. Constructors –Compiler-generated –The Initializer List –Copy Constructors –Single-arg (conversion ctors) The Assignment Operator.
POINTERS.
 2008 Pearson Education, Inc. All rights reserved. 1 Arrays and Vectors.
INTRODUCTION TO MATLAB DAVID COOPER SUMMER Course Layout SundayMondayTuesdayWednesdayThursdayFridaySaturday 67 Intro 89 Scripts 1011 Work
1 Becoming More Effective with C++ … Day Two Stanley B. Lippman
Object-Oriented Programming in C++ Lecture 4 Constants References Operator overloading.
Lecture 5: Expressions and Interactivity Professor: Dr. Miguel Alonso Jr. Fall 2008 CGS2423/COP1220.
EEL 3801 C++ as an Enhancement of C. EEL 3801 – Lotzi Bölöni Comments  Can be done with // at the start of the commented line.  The end-of-line terminates.
Prof. amr Goneid, AUC1 CSCE 110 PROGRAMMING FUNDAMENTALS WITH C++ Prof. Amr Goneid AUC Part 15. Dictionaries (1): A Key Table Class.
Chapter 1 C++ Basics Review (Section 1.4). Classes Defines the organization of a data user-defined type. Members can be  Data  Functions/Methods Information.
CSE 332: C++ pointers, arrays, and references Overview of Pointers and References Often need to refer to another object –Without making a copy of the object.
C++ Basics Programming. COMP104 Lecture 5 / Slide 2 Introduction to C++ l C is a programming language developed in the 1970s with the UNIX operating system.
17-1 Computing Fundamentals with C++ Object-Oriented Programming and Design, 2nd Edition Rick Mercer Franklin, Beedle & Associates, 1999 ISBN
Graphics and Image Data Representations 1. Q1 How images are represented in a computer system? 2.
1 Lecture 4: Part1 Arrays Introduction Arrays  Structures of related data items  Static entity (same size throughout program)
Introduction to Programming Lecture # 43. Math Library Complex number Matrix Quadratic equation and their solution …………….…
C++ Functions A bit of review (things we’ve covered so far)
Java Programming Language Lecture27- An Introduction.
DYNAMIC MEMORY ALLOCATION. Disadvantages of ARRAYS MEMORY ALLOCATION OF ARRAY IS STATIC: Less resource utilization. For example: If the maximum elements.
User-Written Functions
Discussion section #2 HW1 questions?
One-Dimensional Array Introduction Lesson xx
7 Arrays.
Arrays Arrays A few types Structures of related data items
Managing 2D Arrays Simple Dynamic Allocation
SPL – PS1 Introduction to C++.
4.1 Introduction Arrays A few types Structures of related data items
Presentation transcript:

Lecture 10 – Image Processing with OpenCV JJCAO Introduction to C & C++ Lecture 10 – Image Processing with OpenCV JJCAO

OpenCV (Open Source Computer Vision) is a library of programming functions for real time computer vision.

Supported Development Environment Linux, Windows, Android GCC, Eclipse, Visual Studio,

Install OpenCV Basic Info: http://opencv.willowgarage.com/wiki/InstallGuide Necessary steps for Qt Creator (Similar with VS): http://www.laganiere.name/opencvCookbook/chap1.shtml Installation in Windows (too much of details): http://opencv.itseez.com/doc/tutorials/introduction/windows_install/windows_install.html#windows-installation

How to build applications with OpenCV inside the Microsoft Visual Studio http://opencv.itseez.com/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.html#windows-visual-studio-how-to P11 of OpenCV.2.Computer.Vision.Application.Programming.Cookbook_2011

Load & Display an Image Load an image (using imread) Create a named OpenCV window (using namedWindow) Display an image in an OpenCV window (using imshow)

1. Load an image (using imread) cv::Mat image; image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR); // Read the file if( img.empty() ) // Check for invalid input { std::cout << "Could not open or find the image" << std::endl ; return -1; } Image formats supported: Bmp, jpg, png, tif, ppm, … CV_LOAD_IMAGE_UNCHANGED (<0) loads the image as is (including the alpha channel if present) CV_LOAD_IMAGE_GRAYSCALE (0) loads the image as an intensity one CV_LOAD_IMAGE_COLOR (>0) loads the image in the RGB format

2. Create a named OpenCV window (using namedWindow) cv::namedWindow( "Display window", CV_WINDOW_NORMAL|CV_WINDOW_FREERATIO );// Create a window for display. CV_WINDOW_AUTOSIZE is the only supported one if you do not use the Qt backend. In this case the window size will take up the size of the image it shows. No resize permitted! CV_WINDOW_NORMAL on Qt you may use this to allow window resize. The image will resize itself according to the current window size. By using the | operator you also need to specify if you would like the image to keep its aspect ratio (CV_WINDOW_KEEPRATIO) or not (CV_WINDOW_FREERATIO).

3. Display an image in an OpenCV window (using imshow) cv::imshow( "Display window", image ); // Show our image inside it. cv::waitKey(0); // Wait for a keystroke in the window Because we want our window to be displayed until the user presses a key (otherwise the program would end far too quickly), we use the waitKey function whose only parameter is just how long should it wait for a user input (measured in milliseconds). Zero means to wait forever.

Necessary Head Files #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> using namespace cv; using namespace std; You’ll almost always end up using the: core section, as here are defined the basic building blocks of the library highgui module, as this contains the functions for input, output & GUI operations

Necessary libraries #ifdef _DEBUG #pragma comment(lib, "opencv_core230d.lib“ ) #pragma comment(lib, "opencv_highgui230d.lib“ ) #else #pragma comment(lib, "opencv_core230.lib“ ) #pragma comment(lib, "opencv_highgui230.lib“ ) #endif

Congratulation!

From C to C++ OpenCV has been around ever since 2001. In those days the library was built around a C interface. user is responsible for taking care of memory allocation and de-allocation Lots of old tutorials written in C Once your code start to grow larger & larger, more & more a struggle to handle this rather than focusing on solving your goal Finally C++ automatic memory management (more or less) less to write, to achieve more While this is no issue in case of smaller programs once your code base start to grove larger and larger it will be more and more a struggle to handle all this rather than focusing on actually solving your development goal.

int dims; //! the array dimensionality, >= 2 class CV_EXPORTS Mat { public: // ... a lot of methods ... ... /*! includes several bit-fields: the magic signature continuity flag depth number of channels */ int flags; int dims; //! the array dimensionality, >= 2 int rows, cols; //! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions int* refcount; //! pointer to the reference counter; when array points to user-allocated data, the pointer is NULL // other members ... uchar* data; //! pointer to the data }; Head

Create a cv::Mat Mat A, C; // creates just the header parts A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // the method will allocate matrix (deep copy) Mat B(A); // Use the copy constructor, without copying the data (shadow copy) C = A; // Assignment operator, shadow copy Mat roi(A, Rect(10,10,100,100)); // select a ROI roi = Scalar(0,255,0); // fill the ROI with (0,255,0) (which is green in RGB space); the original A will be modified; see next page.

cv::Scalar template <typename _Tp> class Scalar_ : public Vec<_Tp, 4> { ... }; typedef Scalar_<double> Scalar; Being derived from Vec<_Tp, 4> , Scalar_ and Scalar can be used just as typical 4-element vectors.

Deep Copy Mat F = A.clone(); Mat G; A.copyTo(G); Now modifying F or G will not affect the matrix pointed by the Mat header.

What you need to remember Output image allocation for OpenCV functions is automatic (unless specified otherwise). Example (next page) No need to think about memory freeing with OpenCVs C++ interface. The assignment operator and the copy constructor (ctor)copies only the header. Use the clone() or the copyTo() function to copy the underlying matrix of an image.

Output image allocation for OpenCV functions is automatic instead of writing: Mat color; ... Mat gray(color.rows, color.cols, color.depth()); cvtColor(color, gray, CV_BGR2GRAY); you can simply write: Mat gray;

How to scan images, lookup table & time measurement How to go through each and every pixel of an image? How is OpenCV matrix values stored? How to measure the performance of our algorithm? What are lookup tables and why use them? Basic Mat info Storing methods Data type conversion Accessing Pixel Values

a simple color reduction method how_to_scan_images imageName.jpg divideWith [G] if( argc == 4 && !strcmp(argv[3],"G") ) I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); else I = imread(argv[1], CV_LOAD_IMAGE_COLOR); uchar CV_8U CV_8U3

Storing methods How to store pixel values? Color space Data type Gray-level (Black-and-White) unsigned 8-bit values 0: black, 255: white RGB A triplet of unsigned 8-bit values [0, 0, 0]: black, [255, 0, 0]: red, [255, 255, 255]: white HSV, HLS, …, CIE Data type

bool Mat::isContinuous() Matrices created with Mat::create() are always continuous: may no longer continuous extract a part of the matrix using Mat::col(), Mat::diag() , and so on, or constructed a matrix header for externally allocated data. row1 row2 … row n

Storing methods How to store pixel values? Color space Data type Gray-level (Black-and-White) unsigned 8-bit values 0: black, 255: white RGB A triplet of unsigned 8-bit values [0, 0, 0]: black, [255, 0, 0]: red, [255, 255, 255]: white HSV, HLS, …, CIE Data type CV_8U - 8-bit unsigned integers ( 0..255 ) CV_8S - 8-bit signed integers ( -128..127 ) CV_16U - 16-bit unsigned integers ( 0..65535 ) CV_16S - 16-bit signed integers ( -32768..32767 ) CV_32S - 32-bit signed integers ( -2147483648..2147483647 ) CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN ) CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )

Inquire Mat Info int Mat::depth() const int Mat::channels() const int Mat::type() // mixture of depth & channels #define CV_8UC1 CV_MAKETYPE(CV_8U,1) #define CV_8UC2 CV_MAKETYPE(CV_8U,2) #define CV_8UC3 CV_MAKETYPE(CV_8U,3) #define CV_8UC4 CV_MAKETYPE(CV_8U,4) #define CV_8UC(n) CV_MAKETYPE(CV_8U,(n)) … size_t Mat::elemSize() // matrix element (pixel) size in bytes if the matrix type is CV_16SC3 , the method returns3*sizeof(short) or 6. size_t Mat::elemSize1() // element size of a channel in bytes if the matrix type is CV_16SC3 , the method returns sizeof(short) or 2. M.step[] size_t Mat::step1() // a matrix step divided by Mat::elemSize1()

Accessing Pixel Values The efficient way: c style access p = I.ptr<uchar>(i); p[j] The iterator (safe) method On-the-fly address calculation with reference returning I.at<uchar>(i,j) Performance Difference quite large (2560 X 1600) image

Performance Difference Debug Release

More efficient Algorithm divide and multiplication operations are bloody expensive for a system. cheaper operations such as a few subtractions, addition or in best case a simple assignment limited number of input values, 256 to be exact in this problem

Lookup table int divideWith; // convert our input string to number - C++ style stringstream s; s << argv[2]; s >> divideWith; if (!s) { cout << "Invalid number entered for dividing. " << endl; return -1; } uchar table[256]; for (int i = 0; i < 256; ++i) table[i] = divideWith* (i/divideWith);

Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); int channels = I.channels(); int nRows = I.rows; int nCols = I.cols * channels; if (I.isContinuous()) nCols *= nRows; nRows = 1; } int i,j; uchar* p; for( i = 0; i < nRows; ++i) { p = I.ptr<uchar>(i); for ( j = 0; j < nCols; ++j) p[j] = table[p[j]]; } return I;

Basic Mat Info bool Mat::empty() size_t Mat::total() int Mat::rows, Mat::cols Size Mat::size()

Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); const int channels = I.channels(); switch(channels) case 1: { MatIterator_<uchar> it, end; for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it) *it = table[*it]; break; } case 3: { MatIterator_<Vec3b> it, end; for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it) { (*it)[0] = table[(*it)[0]]; (*it)[1] = table[(*it)[1]]; (*it)[2] = table[(*it)[2]]; return I;

Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); const int channels = I.channels(); switch(channels) case 1: { for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ){ I.at<uchar>(i,j) = table[I.at<uchar>(i,j)]; } break; case 3: { Mat_<Vec3b> _I = I; for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ) { _I(i,j)[0] = table[_I(i,j)[0]]; _I(i,j)[1] = table[_I(i,j)[1]]; _I(i,j)[2] = table[_I(i,j)[2]]; } I = _I; break; return I;

The Core Function: cv::LUT() LUT: replace all of given image values to some other values Mat lookUpTable(1, 256, CV_8U); uchar* p = lookUpTable.data; for( int i = 0; i < 256; ++i) p[i] = table[i]; for (int i = 0; i < times; ++i) cv::LUT(I, lookUpTable, J);

Conclusion If possible, use the already made functions of OpenCV (instead reinventing these). The fastest method turns out to be the LUT function. This is because the OpenCV library is multi-thread enabled via Intel Threaded Building Blocks. However, if you need to write a simple image scan prefer the pointer method. The iterator is a safer bet, however quite slower. Using the on-the-fly reference access method for full image scan is the most costly in debug mode. In the release mode it may beat the iterator approach or not, however it surely sacrifices for this the safety trait of iterators.

Type Conversion #include <opencv2/imgproc/imgproc.hpp> cvtColor(I, J, CV_RGB2GRAY); for( int i = 0; i < 0.5*I.rows; ++i) for( int j = 0; j < 0.5*I.cols; ++j ) { //J.at<uchar>(i,j) = 0; J.at<float>(i,j) = 0; } Mat::convertTo()

void Mat::convertTo(OutputArray m, int rtype, double alpha=1, double beta=0 ) Converts an array to another datatype with optional scaling. Parameters: m – Destination matrix. If it does not have a proper size or type before the operation, it is reallocated. rtype – Desired destination matrix type or, rather, the depth since the number of channels are the same as the source has. If rtype is negative, the destination matrix will have the same type as the source. alpha – Optional scale factor. beta – Optional delta added to the scaled values. The method converts source pixel values to the target datatype. saturate_cast<> is applied at the end to avoid possible overflows:

One More Example: gradient infile='data\HappyFish.jpg'; im = imread(infile); info = imfinfo(infile); if ~strcmp(info.ColorType,'grayscale') im = double(rgb2gray(im)) ; end [gx,gy] = gradient(im); figure;colormap(gray); imagesc(im);hold on; [x,y] = meshgrid(1:n,1:m); quiver(x, y, gx,gy);

See the cvMatlab and cvMatlabTest example void jj::gradient(cv::InputArray _src, cv::OutputArray _dst, int xorder) { cv::Mat src=_src.getMat(); _dst.create( src.size(), CV_MAKETYPE(src.depth(), src.channels()) ); cv::Mat dst = _dst.getMat(); … }

See the cvMatlab and cvMatlabTest example Difference in x direction // single channel Mat src, dest; // same size, diff depth for( int i = 0; i < src.rows; ++i) for( int j = 1; j < src.cols-1; ++j ) { dest.at<uchar>(i,j) = (src.at<uchar>(i,j+1) - src.at<uchar>(i,j-1) ) /2.0; } // 3 channels dst.at<cv::Vec3b>(i,j)[0] = (src.at<cv::Vec3b>(i,j+1)[0] - src.at<cv::Vec3b>(i,j-1)[0] ) /2.0; dst.col(j)=(src.col(j+1)-src.col(j-1))/2.0;

Create a Mat object 1 Mat() Mat M(2,2, CV_8UC3, Scalar(0,0,255)); cout << "M = " << endl << " " << M << endl << endl; Create a matrix with more than two dimensions int sz[3] = {2,2,2}; Mat L(3,sz, CV_8UC(1), Scalar::all(0)); // Specify its dimension, then pass a pointer containing the size for each dimension and the rest remains the same. Create a header for an already existing IplImage pointer IplImage* img = cvLoadImage("greatwave.png", 1); Mat mtx(img); // convert IplImage* -> Mat

Create a Mat object 2 Create() function M.create(4,4, CV_8UC(2)); cout << "M = "<< endl << " " << M << endl << endl; // You cannot initialize the matrix values with this construction. It will only reallocate its matrix data memory if the new size will not fit into the old one. MATLAB style initializer: zeros(), ones(), :eyes() Mat E = Mat::eye(4, 4, CV_64F); Mat O = Mat::ones(2, 2, CV_32F); Mat Z = Mat::zeros(3,3, CV_8UC1);

Create a Mat object 3 For small matrices Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); Create a new header for an existing Mat object and clone() or copyTo() it Mat RowClone = C.row(1).clone();

Create a Mat object 4 Create a random matrix with randu() Mat R = Mat(3, 2, CV_8UC3); randu(R, Scalar::all(0), Scalar::all(255)); cout << "R (default) = " << endl << R << endl << endl; cout << "R (python) = " << endl << format(R,"python") << endl << endl; cout << "R (csv) = " << endl << format(R,"csv" ) << endl << endl; …

Resources http://opencv.willowgarage.com/wiki/ C++ Cheatsheet.pdf Online reference manual: 2.3 documentation is here  2008 2011

References OpenCV 2 Computer Vision Application Programming Cookbook, 2011.