├── README.md ├── WebcamStreamingOpenCV ├── README.md └── webcam-opencv-example.py └── face_analysis_sdk ├── main.cpp.diff ├── main[posix].cpp ├── main[w32].cpp └── readme /README.md: -------------------------------------------------------------------------------- 1 | A couple of examples for webcam streaming using OpenCV and porting the face analysis SDK to Windows. 2 | 3 | http://benhowell.github.io/guide/2015/03/09/opencv-and-web-cam-streaming 4 | 5 | http://benhowell.github.io/guide/2015/03/16/porting-face-analysis-sdk-to-windows 6 | -------------------------------------------------------------------------------- /WebcamStreamingOpenCV/README.md: -------------------------------------------------------------------------------- 1 | This code snippet was written to answer a question originating from my video of object recognition and eye tracking here: https://www.youtube.com/watch?v=oIL7ftLkxSE 2 | 3 | A detailed article for this code example can be found here: 4 | http://benhowell.github.io/guide/2015/03/09/opencv-and-web-cam-streaming 5 | -------------------------------------------------------------------------------- /WebcamStreamingOpenCV/webcam-opencv-example.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import cv2 4 | import time 5 | import requests 6 | import threading 7 | from threading import Thread, Event, ThreadError 8 | 9 | class Cam(): 10 | 11 | def __init__(self, url): 12 | 13 | self.stream = requests.get(url, stream=True) 14 | self.thread_cancelled = False 15 | self.thread = Thread(target=self.run) 16 | print "camera initialised" 17 | 18 | 19 | def start(self): 20 | self.thread.start() 21 | print "camera stream started" 22 | 23 | def run(self): 24 | bytes='' 25 | while not self.thread_cancelled: 26 | try: 27 | bytes+=self.stream.raw.read(1024) 28 | a = bytes.find('\xff\xd8') 29 | b = bytes.find('\xff\xd9') 30 | if a!=-1 and b!=-1: 31 | jpg = bytes[a:b+2] 32 | bytes= bytes[b+2:] 33 | img = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR) 34 | cv2.imshow('cam',img) 35 | if cv2.waitKey(1) ==27: 36 | exit(0) 37 | except ThreadError: 38 | self.thread_cancelled = True 39 | 40 | 41 | def is_running(self): 42 | return self.thread.isAlive() 43 | 44 | 45 | def shut_down(self): 46 | self.thread_cancelled = True 47 | #block while waiting for thread to terminate 48 | while self.thread.isAlive(): 49 | time.sleep(1) 50 | return True 51 | 52 | 53 | 54 | if __name__ == "__main__": 55 | url = 'http://192.168.2.1/?action=stream' 56 | cam = Cam(url) 57 | cam.start() 58 | -------------------------------------------------------------------------------- /face_analysis_sdk/main.cpp.diff: -------------------------------------------------------------------------------- 1 | 26,27c26,27 2 | < #include 3 | < #include 4 | --- 5 | > #include 6 | > #include 7 | 67a68 8 | > 9 | 72,76c73,81 10 | < pid_t new_pid = fork(); 11 | < if (new_pid == -1) 12 | < throw make_runtime_error("Unable to fork a new process: %s.", strerror(errno)); 13 | < 14 | < if (new_pid == 0) { // child process 15 | --- 16 | > 17 | > STARTUPINFO si; 18 | > PROCESS_INFORMATION pi; 19 | > 20 | > ZeroMemory( &si, sizeof(si) ); 21 | > si.cb = sizeof(si); 22 | > ZeroMemory( &pi, sizeof(pi) ); 23 | > 24 | > if(!CreateProcess(NULL, "", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){ //child process 25 | 83,84c88,89 26 | < argv[i + 1] = (char *)it->c_str(); 27 | < it++; 28 | --- 29 | > argv[i + 1] = (char *)it->c_str(); 30 | > it++; 31 | 86,99d90 32 | < 33 | < int rv = execvp(command.c_str(), argv); 34 | < if (rv == -1) 35 | < throw make_runtime_error("Unable to create new process: %s.", strerror(errno)); 36 | < } else { // parent process 37 | < int status; 38 | < pid_t wait_pid = waitpid(new_pid, &status, 0); 39 | < if (wait_pid == -1) 40 | < throw make_runtime_error("Unable to wait for process."); 41 | < 42 | < if (WEXITSTATUS(status) != 0) { 43 | < std::stringstream s; 44 | < s << command << " "; 45 | < std::copy(arguments.begin(), arguments.end(), std::ostream_iterator(s, " ")); 46 | 101,102c92,98 47 | < throw make_runtime_error("map-list failed to execute the following command successfully: %s", s.str().c_str()); 48 | < } 49 | --- 50 | > int rv = _execvp(command.c_str(), argv); 51 | > if (rv == -1) 52 | > throw make_runtime_error("Unable to create new process: %s.", strerror(errno)); 53 | > } 54 | > else { // parent process 55 | > throw make_runtime_error("CreateProcess failed (%d).\n", GetLastError() ); 56 | > return; 57 | 103a100,106 58 | > 59 | > // Wait until child process exits. 60 | > WaitForSingleObject( pi.hProcess, INFINITE ); 61 | > 62 | > // Close process and thread handles. 63 | > CloseHandle( pi.hProcess ); 64 | > CloseHandle( pi.hThread ); 65 | -------------------------------------------------------------------------------- /face_analysis_sdk/main[posix].cpp: -------------------------------------------------------------------------------- 1 | // CSIRO has filed various patents which cover the Software. 2 | 3 | // CSIRO grants to you a license to any patents granted for inventions 4 | // implemented by the Software for academic, research and non-commercial 5 | // use only. 6 | 7 | // CSIRO hereby reserves all rights to its inventions implemented by the 8 | // Software and any patents subsequently granted for those inventions 9 | // that are not expressly granted to you. Should you wish to license the 10 | // patents relating to the Software for commercial use please contact 11 | // CSIRO IP & Licensing, Gautam Tendulkar (gautam.tendulkar@csiro.au) or 12 | // Nick Marsh (nick.marsh@csiro.au) 13 | 14 | // This software is provided under the CSIRO OPEN SOURCE LICENSE 15 | // (GPL2) which can be found in the LICENSE file located in the top 16 | // most directory of the source code. 17 | 18 | // Copyright CSIRO 2013 19 | 20 | #include "utils/helpers.hpp" 21 | #include "utils/command-line-arguments.hpp" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | void 30 | print_usage() 31 | { 32 | std::string text = 33 | "Usage: [options] ... [command options]\n" 34 | "\n" 35 | "Options:\n" 36 | " --help This helpful message.\n" 37 | " --echo Do not execute the command, just echo what would be executed\n" 38 | "Read arguments in lists to pass to command as arguments\n"; 39 | 40 | std::cout << text << std::endl; 41 | } 42 | 43 | class Runner 44 | { 45 | public: 46 | virtual void perform(const std::string &command, const std::list &arguments) = 0; 47 | }; 48 | 49 | class EchoRunner : public Runner 50 | { 51 | public: 52 | EchoRunner(std::ostream &stream) 53 | : stream(stream) 54 | { 55 | 56 | } 57 | 58 | void perform(const std::string &command, const std::list &arguments) { 59 | stream << command << " "; 60 | std::copy(arguments.begin(), arguments.end(), std::ostream_iterator(stream, " ")); 61 | stream << std::endl; 62 | } 63 | 64 | private: 65 | std::ostream &stream; 66 | }; 67 | 68 | class ForkRunner : public Runner 69 | { 70 | public: 71 | void perform(const std::string &command, const std::list &arguments) { 72 | pid_t new_pid = fork(); 73 | if (new_pid == -1) 74 | throw make_runtime_error("Unable to fork a new process: %s.", strerror(errno)); 75 | 76 | if (new_pid == 0) { // child process 77 | char *argv[arguments.size() + 2]; 78 | argv[0] = (char *)command.c_str(); 79 | argv[arguments.size() + 1] = 0; 80 | 81 | std::list::const_iterator it = arguments.begin(); 82 | for (size_t i = 0; i < arguments.size(); i++) { 83 | argv[i + 1] = (char *)it->c_str(); 84 | it++; 85 | } 86 | 87 | int rv = execvp(command.c_str(), argv); 88 | if (rv == -1) 89 | throw make_runtime_error("Unable to create new process: %s.", strerror(errno)); 90 | } else { // parent process 91 | int status; 92 | pid_t wait_pid = waitpid(new_pid, &status, 0); 93 | if (wait_pid == -1) 94 | throw make_runtime_error("Unable to wait for process."); 95 | 96 | if (WEXITSTATUS(status) != 0) { 97 | std::stringstream s; 98 | s << command << " "; 99 | std::copy(arguments.begin(), arguments.end(), std::ostream_iterator(s, " ")); 100 | 101 | throw make_runtime_error("map-list failed to execute the following command successfully: %s", s.str().c_str()); 102 | } 103 | } 104 | } 105 | }; 106 | 107 | int 108 | run_program(int argc, char **argv) 109 | { 110 | CommandLineArgument number_of_list_files; 111 | int next_command_line_argument = 0; 112 | bool echo_commands = false; 113 | 114 | for (int i = 1; ((i < argc) && (!have_argument_p(number_of_list_files))); i++) { 115 | std::string argument(argv[i]); 116 | if (argument == "--help") { 117 | print_usage(); 118 | return 0; 119 | } else if (argument == "--echo") { 120 | echo_commands = true; 121 | } else if (!have_argument_p(number_of_list_files)) { 122 | number_of_list_files = argument; 123 | next_command_line_argument = i + 1; 124 | } 125 | } 126 | 127 | if (!have_argument_p(number_of_list_files)) { 128 | print_usage(); 129 | return -1; 130 | } 131 | 132 | if (*number_of_list_files == 0) 133 | return 0; 134 | 135 | const int minimum_number_of_arguments = 0 136 | + *number_of_list_files 137 | + 1 // the command; 138 | + 0; 139 | 140 | if ((argc - next_command_line_argument) < minimum_number_of_arguments) 141 | throw make_runtime_error("Not enough arguments available for processing.\n"); 142 | 143 | std::list standard_input_list; 144 | bool have_read_standard_input_list = false; 145 | 146 | std::vector list_filenames(*number_of_list_files); 147 | std::vector > lists(*number_of_list_files); 148 | for (int i = 0; i < *number_of_list_files; i++) { 149 | int argument_index = i + next_command_line_argument; 150 | std::string list_file = argv[argument_index]; 151 | std::list l; 152 | 153 | if ((list_file == "-") && (have_read_standard_input_list)) { 154 | l = standard_input_list; 155 | } else if ((list_file == "-")) { 156 | standard_input_list = read_list(std::cin); 157 | have_read_standard_input_list = true; 158 | l = standard_input_list; 159 | } else if (!file_exists_p(list_file)) { 160 | throw make_runtime_error("List file %s does not exist.", list_file.c_str()); 161 | } else { 162 | l = read_list(list_file.c_str()); 163 | } 164 | 165 | list_filenames[i] = list_file; 166 | lists[i] = l; 167 | } 168 | next_command_line_argument += *number_of_list_files; 169 | 170 | // read the command and its options. 171 | std::string command(argv[next_command_line_argument]); 172 | std::list command_arguments; 173 | std::copy(argv + next_command_line_argument + 1, argv + argc, std::back_inserter(command_arguments)); 174 | 175 | // check all lists are the same size. 176 | for (size_t i = 0; i < lists.size(); i++) { 177 | if (lists[i].size() != lists[0].size()) 178 | throw make_runtime_error("The number of entires in list %s (%d) differs to %s (%d).", 179 | list_filenames[i].c_str(), 180 | lists[i].size(), 181 | list_filenames[0].c_str(), 182 | lists[0].size()); 183 | } 184 | 185 | EchoRunner echo_runner(std::cout); 186 | ForkRunner fork_runner; 187 | 188 | Runner *runner = 0; 189 | if (echo_commands) 190 | runner = &echo_runner; 191 | else 192 | runner = &fork_runner; 193 | 194 | assert(runner); 195 | std::vector::const_iterator> iterators(*number_of_list_files); 196 | for (int i = 0; i < *number_of_list_files; i++) 197 | iterators[i] = lists[i].begin(); 198 | 199 | for (size_t i = 0; i < lists[0].size(); i++) { 200 | std::string invocation_command = command; 201 | std::list invocation_arguments; 202 | std::copy(command_arguments.begin(), command_arguments.end(), std::back_inserter(invocation_arguments)); 203 | for (size_t j = 0; j < iterators.size(); j++) { 204 | invocation_arguments.push_back(*iterators[j]); 205 | iterators[j]++; 206 | } 207 | 208 | runner->perform(invocation_command, invocation_arguments); 209 | } 210 | 211 | return 0; 212 | } 213 | 214 | int 215 | main(int argc, char **argv) 216 | { 217 | try { 218 | return run_program(argc, argv); 219 | } catch (std::exception &e) { 220 | std::cerr << "Caught unhandled exception: " << e.what() << std::endl; 221 | return -1; 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /face_analysis_sdk/main[w32].cpp: -------------------------------------------------------------------------------- 1 | // CSIRO has filed various patents which cover the Software. 2 | 3 | // CSIRO grants to you a license to any patents granted for inventions 4 | // implemented by the Software for academic, research and non-commercial 5 | // use only. 6 | 7 | // CSIRO hereby reserves all rights to its inventions implemented by the 8 | // Software and any patents subsequently granted for those inventions 9 | // that are not expressly granted to you. Should you wish to license the 10 | // patents relating to the Software for commercial use please contact 11 | // CSIRO IP & Licensing, Gautam Tendulkar (gautam.tendulkar@csiro.au) or 12 | // Nick Marsh (nick.marsh@csiro.au) 13 | 14 | // This software is provided under the CSIRO OPEN SOURCE LICENSE 15 | // (GPL2) which can be found in the LICENSE file located in the top 16 | // most directory of the source code. 17 | 18 | // Copyright CSIRO 2013 19 | 20 | #include "utils/helpers.hpp" 21 | #include "utils/command-line-arguments.hpp" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | void 30 | print_usage() 31 | { 32 | std::string text = 33 | "Usage: [options] ... [command options]\n" 34 | "\n" 35 | "Options:\n" 36 | " --help This helpful message.\n" 37 | " --echo Do not execute the command, just echo what would be executed\n" 38 | "Read arguments in lists to pass to command as arguments\n"; 39 | 40 | std::cout << text << std::endl; 41 | } 42 | 43 | class Runner 44 | { 45 | public: 46 | virtual void perform(const std::string &command, const std::list &arguments) = 0; 47 | }; 48 | 49 | class EchoRunner : public Runner 50 | { 51 | public: 52 | EchoRunner(std::ostream &stream) 53 | : stream(stream) 54 | { 55 | 56 | } 57 | 58 | void perform(const std::string &command, const std::list &arguments) { 59 | stream << command << " "; 60 | std::copy(arguments.begin(), arguments.end(), std::ostream_iterator(stream, " ")); 61 | stream << std::endl; 62 | } 63 | 64 | private: 65 | std::ostream &stream; 66 | }; 67 | 68 | 69 | class ForkRunner : public Runner 70 | { 71 | public: 72 | void perform(const std::string &command, const std::list &arguments) { 73 | 74 | STARTUPINFO si; 75 | PROCESS_INFORMATION pi; 76 | 77 | ZeroMemory( &si, sizeof(si) ); 78 | si.cb = sizeof(si); 79 | ZeroMemory( &pi, sizeof(pi) ); 80 | 81 | if(!CreateProcess(NULL, "", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){ //child process 82 | char *argv[arguments.size() + 2]; 83 | argv[0] = (char *)command.c_str(); 84 | argv[arguments.size() + 1] = 0; 85 | 86 | std::list::const_iterator it = arguments.begin(); 87 | for (size_t i = 0; i < arguments.size(); i++) { 88 | argv[i + 1] = (char *)it->c_str(); 89 | it++; 90 | } 91 | 92 | int rv = _execvp(command.c_str(), argv); 93 | if (rv == -1) 94 | throw make_runtime_error("Unable to create new process: %s.", strerror(errno)); 95 | } 96 | else { // parent process 97 | throw make_runtime_error("CreateProcess failed (%d).\n", GetLastError() ); 98 | return; 99 | } 100 | 101 | // Wait until child process exits. 102 | WaitForSingleObject( pi.hProcess, INFINITE ); 103 | 104 | // Close process and thread handles. 105 | CloseHandle( pi.hProcess ); 106 | CloseHandle( pi.hThread ); 107 | } 108 | }; 109 | 110 | int 111 | run_program(int argc, char **argv) 112 | { 113 | CommandLineArgument number_of_list_files; 114 | int next_command_line_argument = 0; 115 | bool echo_commands = false; 116 | 117 | for (int i = 1; ((i < argc) && (!have_argument_p(number_of_list_files))); i++) { 118 | std::string argument(argv[i]); 119 | if (argument == "--help") { 120 | print_usage(); 121 | return 0; 122 | } else if (argument == "--echo") { 123 | echo_commands = true; 124 | } else if (!have_argument_p(number_of_list_files)) { 125 | number_of_list_files = argument; 126 | next_command_line_argument = i + 1; 127 | } 128 | } 129 | 130 | if (!have_argument_p(number_of_list_files)) { 131 | print_usage(); 132 | return -1; 133 | } 134 | 135 | if (*number_of_list_files == 0) 136 | return 0; 137 | 138 | const int minimum_number_of_arguments = 0 139 | + *number_of_list_files 140 | + 1 // the command; 141 | + 0; 142 | 143 | if ((argc - next_command_line_argument) < minimum_number_of_arguments) 144 | throw make_runtime_error("Not enough arguments available for processing.\n"); 145 | 146 | std::list standard_input_list; 147 | bool have_read_standard_input_list = false; 148 | 149 | std::vector list_filenames(*number_of_list_files); 150 | std::vector > lists(*number_of_list_files); 151 | for (int i = 0; i < *number_of_list_files; i++) { 152 | int argument_index = i + next_command_line_argument; 153 | std::string list_file = argv[argument_index]; 154 | std::list l; 155 | 156 | if ((list_file == "-") && (have_read_standard_input_list)) { 157 | l = standard_input_list; 158 | } else if ((list_file == "-")) { 159 | standard_input_list = read_list(std::cin); 160 | have_read_standard_input_list = true; 161 | l = standard_input_list; 162 | } else if (!file_exists_p(list_file)) { 163 | throw make_runtime_error("List file %s does not exist.", list_file.c_str()); 164 | } else { 165 | l = read_list(list_file.c_str()); 166 | } 167 | 168 | list_filenames[i] = list_file; 169 | lists[i] = l; 170 | } 171 | next_command_line_argument += *number_of_list_files; 172 | 173 | // read the command and its options. 174 | std::string command(argv[next_command_line_argument]); 175 | std::list command_arguments; 176 | std::copy(argv + next_command_line_argument + 1, argv + argc, std::back_inserter(command_arguments)); 177 | 178 | // check all lists are the same size. 179 | for (size_t i = 0; i < lists.size(); i++) { 180 | if (lists[i].size() != lists[0].size()) 181 | throw make_runtime_error("The number of entires in list %s (%d) differs to %s (%d).", 182 | list_filenames[i].c_str(), 183 | lists[i].size(), 184 | list_filenames[0].c_str(), 185 | lists[0].size()); 186 | } 187 | 188 | EchoRunner echo_runner(std::cout); 189 | ForkRunner fork_runner; 190 | 191 | Runner *runner = 0; 192 | if (echo_commands) 193 | runner = &echo_runner; 194 | else 195 | runner = &fork_runner; 196 | 197 | assert(runner); 198 | std::vector::const_iterator> iterators(*number_of_list_files); 199 | for (int i = 0; i < *number_of_list_files; i++) 200 | iterators[i] = lists[i].begin(); 201 | 202 | for (size_t i = 0; i < lists[0].size(); i++) { 203 | std::string invocation_command = command; 204 | std::list invocation_arguments; 205 | std::copy(command_arguments.begin(), command_arguments.end(), std::back_inserter(invocation_arguments)); 206 | for (size_t j = 0; j < iterators.size(); j++) { 207 | invocation_arguments.push_back(*iterators[j]); 208 | iterators[j]++; 209 | } 210 | 211 | runner->perform(invocation_command, invocation_arguments); 212 | } 213 | 214 | return 0; 215 | } 216 | 217 | int 218 | main(int argc, char **argv) 219 | { 220 | try { 221 | return run_program(argc, argv); 222 | } catch (std::exception &e) { 223 | std::cerr << "Caught unhandled exception: " << e.what() << std::endl; 224 | return -1; 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /face_analysis_sdk/readme: -------------------------------------------------------------------------------- 1 | code for article: http://benhowell.github.io/guide/2015/03/16/porting-face-analysis-sdk-to-windows 2 | --------------------------------------------------------------------------------