Home » wulan kandiani kusumah wardani » Source SMART MIRROR Source SMART MIRROR wulan kandiani kusumah wardani 08.52 wulan kandiani kusumah wardani 1. Ketikan Source Program .cpp /** Main Include Files **/ #include "stdafx.h" #include #include #include #include #include #include #include #include #include #include #include "JnS.h" #include "Matutil.h" #include "SerialClass.h" #pragma comment(lib, "ws2_32.lib") /** Text to Speech Configuration **/ #include #define _ATL_APARTMENT_THREADED #include extern CComModule _Module; #include /** Using Namespaces **/ using namespace cv; using namespace std; /** Default Parameters **/ bool arduino_ready = true; // true if arduino is ready, false if not bool debug_information = true; // true if power spectrums are displayed, false if not bool gui_new = true; // true if use new GUI, false if not bool log_on = true; // set true to activate log fiture, false if not bool save_all_image = true;// set true if save all image, false if not bool send_to_database = false; // true if the program needs to create socket, false if not bool speak_on = true; // true if speaker is active, false if not bool use_webcam = true; // true if using webcam, false if using video sample int frame_height = 480; // height of frame int frame_rate = 15; // frame rate of captured video int frame_width = 640; // width of frame int port_number = 8888; // database port number int total_time = 15; // total time of measurement in second char* arduino_port = "COM22"; // name of arduino port char* host_name = "localhost"; // database host name char* sample_video_name = "sample1.mov"; // name of video file String User = "dear"; // name of user /** Constants **/ const int bt_max = 50; // maximum body temperature can be measured const int bt_min = 10; // minimum body temperature can be measured const int hr_good_max = 100; // good of heart rate const int hr_good_min = 60; // good of heart rate const int hr_max = 100; // maximum heart rate can be measured const int hr_min = 60; // minimum heart rate can be measured const int rr_max = 32; // maximum respiration rate can be measure const int rr_min = 8; // minimum respiration rate can be measured const String DisplayWindow = "UBI-Healtcare System: Healthy Mirror"; // name of display window const String FaceCascadeName = "haarcascade_frontalface_default.xml"; // name of face cascade const String FrameWindow = "Healthy Mirror v1.3"; // name of video window const String ResultWindow = "Result"; // name of result window /** Global Variables of Program **/ bool finish; // as finish impulse bool validity; // true if there is no slow processing time char message[100]; // as message to be sent int count_down; // as iterator when face dissapear int fft_size; // size of FFT int i; // as iterator of saved image int n_result; // to save number of saved result int sampling_periode; // sampling periode, used for delay between frame captured int start_iterator; // start of iterator int total_data; // number of frame sample String LogFileName; // to save name of log file SOCKET Socket; // as SOCKET for connecting to server SOCKADDR_IN SockAddr; // as SOCKADDR_IN for connecting to server std::ofstream MyFile; // to write log file Mat Display(768, 1366, CV_8U, Scalar(0)); // as the main GUI /** Global Variables of Heart Rate **/ bool face_detected; // as a flag whether face is detected or not double previous_mean_green; // to save previous mean of green channel int heart_rate; // to save heart rate int heart_rate_c; // to save index of selected independent component for heart rate int heart_rate_r_1, heart_rate_g_1, heart_rate_b_1; // to save heart rate from 3 trace signal int heart_rate_c1_1, heart_rate_c2_1, heart_rate_c3_1; // to save heart rate from 3 independent signal int heart_rate_r_2, heart_rate_g_2, heart_rate_b_2; // to save 2nd heart rate from 3 trace signal int heart_rate_c1_2, heart_rate_c2_2, heart_rate_c3_2; // to save 2nd heart rate from 3 independent signal CascadeClassifier FaceCascade; // an object of cascade classifier Rect PreviousFace; // to save previous face detected Rect TempFace; // to save temporary face detected Scalar MeanXi; // to save mean for calculating Xin(t) Scalar StdDevXi; // to save standard deviation to calculating Xin(t) Mat DrawHRPSC1(150, hr_max*2, CV_8UC3, Scalar(255,255,255)); // to draw power spectrum of 1st component of heart rate Mat DrawHRPSC2(150, hr_max*2, CV_8UC3, Scalar(255,255,255)); // to draw power spectrum of 2nd component of heart rate Mat DrawHRPSC3(150, hr_max*2, CV_8UC3, Scalar(255,255,255)); // to draw power spectrum of 3rd component of heart rate Mat DrawHRPSB(150, hr_max*2, CV_8UC3, Scalar(255,255,255)); // to draw power spectrum of blue component of heart rate Mat DrawHRPSG(150, hr_max*2, CV_8UC3, Scalar(255,255,255)); // to draw power spectrum of green component of heart rate Mat DrawHRPSR(150, hr_max*2, CV_8UC3, Scalar(255,255,255)); // to draw power spectrum of red component of heart rate Mat DrawResult(150, 300, CV_8U, Scalar(255)); // to draw result Mat Frame; // frame of video Mat ROI; // ROI of video Mat ImageGray; // gray image Mat XiT; // to save Xi(t) Mat XinT; // to save Xin(t) /* Global Variables of Respiration Rate */ int current; // to save index of current image int previous; // to save index of previous image int respiration_rate; // to save respiration rate int rr_roi_x; // x position of RR ROI int rr_roi_y; // y position of RR ROI int rr_roi_width; // width of RR ROI int rr_roi_height; // height of RR ROI int total_frame; // number of buffered frame Mat DrawRRPS(150, rr_max*2, CV_8UC3, Scalar(255,255,255)); // to draw power spectrum of respiration rate Mat DrawRRSignal; // to plot signal of respiration rate Mat SmoothenData; // to save SmoothenData of sum of pixel Mat Subtracted; // to save Subtracted image Mat SumT; // to save sum of pixel in time Mat Thresholded; // to save Thresholded image /* Global Variables of Body Temperature */ float body_temperature; // to save body temperature result Serial* SP; // as Serial* to receive data from arduino /** Function Absolute **/ int Absolute (int a) { // to find absolute value of an integer input a if (a < 0) return -a; else return a; } /** Function ChangeInteger **/ void ChangeInteger (int &a, int &b) { // to change value between two integer variable int c = a; a = b; b = c; } /** Function CharToInt **/ int CharToInt (char cc) { // to convert cc char to int switch (cc) { case '1': {return 1; break;} case '2': {return 2; break;} case '3': {return 3; break;} case '4': {return 4; break;} case '5': {return 5; break;} case '6': {return 6; break;} case '7': {return 7; break;} case '8': {return 8; break;} case '9': {return 9; break;} case '0': {return 0; break;} default : return -1; } } /** Function CharsToInt **/ int CharsToInt (char cc[4]) { // to convert 4 digit cc char to int if (CharToInt(cc[1]) < 0) { // < 10 return (CharToInt(cc[0])); } else if (CharToInt(cc[2]) < 0) { // < 100 return (CharToInt(cc[1]) + (10*CharToInt(cc[0]))); } else if (CharToInt(cc[3]) < 0) { // < 1000 return (CharToInt(cc[2]) + (10*CharToInt(cc[1])) + (100*CharToInt(cc[0]))); } else { // < 10000 return (CharToInt(cc[3]) + (10*CharToInt(cc[2])) + (100*CharToInt(cc[1])) + (1000*CharToInt(cc[0]))); } } /** Function GetUser #1 **/ String GetUser (char cc[8]) { // to get 8 first character of cc String temp = cc; if (temp.size() > 8) { temp = ""; for (int z = 0; z < 8; z++){ temp += cc[z]; } } return temp; } /**mark**/ /** Function GetUser #2 **/ String GetUser (String Cc) { // to get 8 first character of Cc String temp = Cc; if (temp.size() > 8) { temp = ""; for (int z = 0; z < 8; z++){ temp += Cc[z]; } } return temp; } /** Procedure ChangeParameter **/ void ChangeParameter (char c1[2], char c2[30]) { // to change parameter switch (c1[1]) { case 'z': { if ((CharToInt(c2[0]) == 0) || (c2[0] == 'f')) { speak_on = false; } else { speak_on = true; } cout< IsConnected()){ // check if the port is connect SP -> WriteData(command, 1); result = SP->ReadData(buffer, 4); // to read sent data from arduino if (result != -1) { break; } } // Convert sent data to float float temp = (float)(CharToInt(buffer[0])*10); temp += (float)(CharToInt(buffer[1])); temp += (float)(CharToInt(buffer[3])*0.1); SP -> ~Serial(); // disconect return temp; } else return 0; } /** Function StringToWString **/ wstring StringToWstring(const String& s) { // to convert String to WString int len; int slength = (int)s.length() + 1; len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); wchar_t* buf = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len); std::wstring r(buf); delete[] buf; return r; } /** Function StringToSpeak **/ int StringToSpeak (const std::string& s) { // to convert string in to speak ISpVoice * pVoice = NULL; if (FAILED(::CoInitialize(NULL))) return -1; HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice); if( SUCCEEDED( hr ) ) { std::wstring stemp = StringToWstring(s); LPCWSTR result = stemp.c_str(); hr = pVoice->Speak(result, 0, NULL); pVoice->Release(); pVoice = NULL; } ::CoUninitialize(); return 0; } /** Procedure UserOnDisplay **/ void UserOnDisplay () { // to show User on display Display = Scalar(0); // blacken Display stringstream TextUser; // create stringstream variable TextUser<<"hi "< 0) { // Ready every couple of parameter int argn = argc-1; while (argn > 0) { ChangeParameter(argv[argn-1], argv[argn]); argn -= 2; } // Show "<<< START MEASURING >>>" cout<>>"<Faces; // Set wheter to open the video file or webcam VideoCapture Capture; if (use_webcam) { // Open capture from (1) external or (2) internal webcam Capture = VideoCapture(-1); // Set size of captured frame if (frame_height > frame_width) { // portrait Capture.VideoCapture::set(CV_CAP_PROP_FRAME_WIDTH, frame_height); Capture.VideoCapture::set(CV_CAP_PROP_FRAME_HEIGHT, frame_width); } else { // landscape Capture.VideoCapture::set(CV_CAP_PROP_FRAME_WIDTH, frame_width); Capture.VideoCapture::set(CV_CAP_PROP_FRAME_HEIGHT, frame_height); } } else { // use sample video // Set size of captured frame Capture = VideoCapture(sample_video_name); // Get frame size frame_width = Capture.VideoCapture::get(CV_CAP_PROP_FRAME_WIDTH); frame_height = Capture.VideoCapture::get(CV_CAP_PROP_FRAME_HEIGHT); // Get frame rate if (Capture.VideoCapture::get(CV_CAP_PROP_FPS) < 50) { // error handling frame_rate = Capture.VideoCapture::get(CV_CAP_PROP_FPS); } // Recalculate other parameter because of frame rate parameter changing FrameRateChanged(); } // Check if video successfully opened if (!Capture.isOpened()) { // Show debug information cout<<"Error loading video\n"; return 1; } /// RR1. Initiate Respiration Rate // RR - Set ROI size Capture.read(Frame); if (frame_height > frame_width) { // portrait rr_roi_x = (int)(Frame.rows/4); rr_roi_y = (int)(Frame.cols*2/3); rr_roi_width = (int)(Frame.rows/2); rr_roi_height = (int)(Frame.cols/3); } else { // landscape rr_roi_x = (int)(Frame.cols/4); rr_roi_y = (int)(Frame.rows/2); rr_roi_width = (int)(Frame.cols/2); rr_roi_height = (int)(Frame.rows/2); } // RR - Set last 0.5 second frames as black images vector LastFrames(total_frame); // to save last 0.5 second frames for (int i = 0; i < total_frame; i++) { LastFrames[i] = Mat(rr_roi_height, rr_roi_width, CV_8U, Scalar(0)); } // Create images windows if (gui_new) { // Show window namedWindow(DisplayWindow, 0); // Set window to fullscreen mode setWindowProperty(DisplayWindow, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN); // Hide Cursor ShowCursor(false); // Enable mouse event for new GUI setMouseCallback(DisplayWindow, mouseEvent, 0); } else { // old GUI // Show windows namedWindow(FrameWindow); namedWindow(ResultWindow); } /*** Main Loop ***/ while (1) { // Read next frame if any if (!Capture.read(Frame)) break; // Start counting duration double duration = static_cast(getTickCount()); // Transpose frame if portrait enable if (frame_height > frame_width) { transpose(Frame, Frame); } // Convert to gray scale image cvtColor(Frame, ImageGray, CV_BGR2GRAY); // RR - Select ROI Mat selected(ImageGray, Rect(rr_roi_x, rr_roi_y, rr_roi_width, rr_roi_height)); // RR - Copy selected image to current image selected.copyTo(LastFrames[current]); // RR - Draw rectangle on selected ROI rectangle(Frame, Rect(rr_roi_x, rr_roi_y, rr_roi_width, rr_roi_height), Scalar(200,200,200), 1, 8, 0); // HR - Calculate hystogram equalizeHist(ImageGray, ImageGray); // HR - Detect faces if (!face_detected) { // no face was detected, searching from 50x50 size of image FaceCascade.detectMultiScale(ImageGray, Faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(100, 100)); // its default is Size(20,20)) } else { // face was detected, adapting from previous face size int a; if (PreviousFace.width > PreviousFace.height) { a = PreviousFace.height*0.8; } else { a = PreviousFace.width*0.8; } if (a > 100) { // be careful of using this constant, depend on video resolution // be careful of using Size(2*a,2*a) below FaceCascade.detectMultiScale(ImageGray, Faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(a,a), Size(2*a,2*a)); } else { FaceCascade.detectMultiScale(ImageGray, Faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(100, 100)); // its default is Size(20,20)) } } if (Faces.size() > 0) { // HR - Set flag of face_detected when face appear face_detected = true; count_down = -frame_rate; // HR - Handle false alarm TempFace = Faces[0]; if (Faces.size() > 1) { // HR - Find the closest x coordinate to previous face coordinate int diff = Absolute(Faces[0].x - PreviousFace.x); for (int k=1; k < Faces.size(); k++) { if (Absolute(Faces[k].x - PreviousFace.x) < diff) { diff = Absolute(Faces[k].x - PreviousFace.x); TempFace = Faces[k]; } } } } else { // Faces.size() = 0 // HR - Handle missing detection and face dissapear if (face_detected) { // HR - Get roi from previous face coordinate ROI = Mat(Frame, PreviousFace); // HR - Get difference of the temporary roi from the previous one double a = mean(ROI).val[1] - previous_mean_green; // HR - Get Absolute of the difference if (a < 0) a = -a; if ((a < 10) && (i > -10)) { // be careful of using a constant // HR - Missing detection. Using the coordinate of previous face TempFace = PreviousFace; } else { // HR - Face dissapear face_detected = false; } } } // When user dissapear if (count_down == 0) { if (gui_new) { // Show black image on display Display = Scalar(0); // Display waiting putText(Display, "Menunggu user :)", Point(100, 400), 0, 5, Scalar(255), 5); } else { // old GUI // Whitenning DrawResult DrawResult = Scalar(255); // Whitenning heart rate power spectrum DrawHRPSC1 = Scalar(255, 255, 255); DrawHRPSC2 = Scalar(255, 255, 255); DrawHRPSC3 = Scalar(255, 255, 255); DrawHRPSR = Scalar(255, 255, 255); DrawHRPSG = Scalar(255, 255, 255); DrawHRPSB = Scalar(255, 255, 255); // Whitenning DrawRRSignal DrawRRSignal = Scalar(255); // Display waiting putText(DrawResult, "waiting...", Point(50,80), 0, 1, Scalar(0), 1); } // HR - Set HR to 0 heart_rate = 0; } if (face_detected) { // Restart count down count_down = -frame_rate; // HR - Copy TempFace to PreviousFace PreviousFace = TempFace; // HR - Adjust face size TempFace.x = TempFace.x + TempFace.width*0.2; TempFace.width *= 0.6; // HR - Draw a rectangle lied on the face detected rectangle(Frame, TempFace, Scalar(100,255,50), 1, 8, 0); // HR - Create ROI from face detected ROI = Mat(Frame, TempFace); /// HR2. Get Xi(t) and Xin(t) // HR - Get mean of each R,G,B image and save on XiT Mat Scalar mean_frame = mean(ROI); double r = mean_frame.val[2]; double g = mean_frame.val[1]; double b = mean_frame.val[0]; previous_mean_green = b; /// RR2. Get sum(t) from selected ROI // RR - Subtract current selected image with selected image of 0,5 second ago subtract(LastFrames[current], LastFrames[previous], Subtracted); // RR - Smoothing subtracted image GaussianBlur(Subtracted, Subtracted, Size(7, 7), 0, 0); // RR - Threshold to binary image threshold(Subtracted, Thresholded, 10, 255, THRESH_BINARY); // RR - Calculate and normalize the sum of pixel value Scalar SumPixel = sum(Thresholded); double normalized_sum = ((SumPixel.val[0]*50)/(480*240)); // Display stabilizing or greeting if (heart_rate == 0) { if (gui_new) { // Display greeting if (i == -20) { UserOnDisplay(); } // Say greeting if ((i == -10) && (speak_on) /* && (LastUser != User) */) { StringToSpeak("Hi "+User+". please wait while we're measuring your body vital signs"); } } else if (!gui_new && (i == start_iterator)) { // Display stabilizing DrawResult = Scalar(255); putText(DrawResult, "stabilizing...", Point(50,80), 0, 1, Scalar(0), 1); } } if ((i >= 0) && (i < total_data)) { //Create Progress if(i > 0) { double progressNum = (double)i/(double)total_data * 100.0; UserOnDisplayWithProgress((int)progressNum); } /** Tracing Frames **/ // Set validity true if (i == 0) { validity = true; } // RR - Save sum of pixel value in to array SumT.at(0, i) = normalized_sum; // Display processing if ((heart_rate == 0) && (!gui_new) && (i == 0)) { DrawResult = Scalar(255); putText(DrawResult, "processing...", Point(50,80), 0, 1, Scalar(0), 1); } // HR - Save R,G,B mean to XiT XiT.at(0,i)[2] = r; XiT.at(0,i)[1] = g; XiT.at(0,i)[0] = b; } else if (i == total_data) { /** Processing Frames **/ // RR - Smoothing data with filter2d Mat Kernel = Mat(1, 11, CV_64F, Scalar(0.1)); filter2D(SumT, SmoothenData, SumT.depth(), Kernel); /// RR3. Get Respiration Rate // HR - Copy respiration signal in to InputFFTRR Mat InputFFTRR(1, fft_size, CV_64F, cv::Scalar(0)); for (int j = 0; j < total_data; j++) { InputFFTRR.at(j) = SmoothenData.at(0,j); } // HR - Get FFT result magnitude from respiration rate Mat planesRR[] = {Mat_(InputFFTRR), Mat::zeros(InputFFTRR.size(), CV_64F)}; Mat complexIRR; merge(planesRR, 2, complexIRR); // Add to the expanded another plane with zeros dft(complexIRR, complexIRR); // this way the result may fit in the source matrix split(complexIRR, planesRR); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) magnitude(planesRR[0], planesRR[1], planesRR[0]); // planes[0] = magnitude Mat MagnitudeRR = planesRR[0]; // RR - Get power spectrum Mat PowerSpectrumRR(1, rr_max, CV_64F); for (int j = 0; j < rr_max; j++) { PowerSpectrumRR.at(j) = MagnitudeRR.at(j)*MagnitudeRR.at(j); } // RR - Searching for frequency with highest power spectrum double rr_index_temp = 0; int rr_temp; for (int j = rr_min; j < rr_max; j++) { if (rr_index_temp < PowerSpectrumRR.at(j)) { rr_index_temp = PowerSpectrumRR.at(j); rr_temp = j; } } respiration_rate = rr_temp; // HR - Get mean and standard deviation of raw image meanStdDev(XiT, MeanXi, StdDevXi); // HR - Save normalized XiT to XinT for (int j = 0; j < total_data; j++) { r = (XiT.at(0,j)[2] - MeanXi.val[2])/StdDevXi.val[2]; XinT.at(0,j)[2] = r; g = (XiT.at(0,j)[1] - MeanXi.val[1])/StdDevXi.val[1]; XinT.at(0,j)[1] = g; b = (XiT.at(0,j)[0] - MeanXi.val[0])/StdDevXi.val[0]; XinT.at(0,j)[0] = b; } // HR - Copy 3 trace signal in to InputFFT Mat InputFFTR(1, fft_size, CV_64F, cv::Scalar(0)); Mat InputFFTG(1, fft_size, CV_64F, cv::Scalar(0)); Mat InputFFTB(1, fft_size, CV_64F, cv::Scalar(0)); for (int j = 0; j < total_data; j++) { InputFFTR.at(j) = XinT.at(0,j)[2]; InputFFTG.at(j) = XinT.at(0,j)[1]; InputFFTB.at(j) = XinT.at(0,j)[0]; } // HR - Get FFT result magnitude from red component Mat planesR[] = {Mat_(InputFFTR), Mat::zeros(InputFFTR.size(), CV_64F)}; Mat complexIR; merge(planesR, 2, complexIR); // Add to the expanded another plane with zeros dft(complexIR, complexIR); // this way the result may fit in the source matrix split(complexIR, planesR); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) magnitude(planesR[0], planesR[1], planesR[0]); // planes[0] = magnitude Mat MagnitudeR = planesR[0]; // HR - Get FFT result magnitude from green component Mat planesG[] = {Mat_(InputFFTG), Mat::zeros(InputFFTG.size(), CV_64F)}; Mat complexIG; merge(planesG, 2, complexIG); // Add to the expanded another plane with zeros dft(complexIG, complexIG); // this way the result may fit in the source matrix split(complexIG, planesG); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) magnitude(planesG[0], planesG[1], planesG[0]); // planes[0] = magnitude Mat MagnitudeG = planesG[0]; // HR - Get FFT result magnitude from blue component Mat planesB[] = {Mat_(InputFFTB), Mat::zeros(InputFFTB.size(), CV_64F)}; Mat complexIB; merge(planesB, 2, complexIB); // Add to the expanded another plane with zeros dft(complexIB, complexIB); // this way the result may fit in the source matrix split(complexIB, planesB); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) magnitude(planesB[0], planesB[1], planesB[0]); // planes[0] = magnitude Mat MagnitudeB = planesB[0]; /// HR3. Get Independent Component // HR - Create array of double for both input and output of ICA double *ica_matrix; double *ica_signal; if ((ica_matrix = (double *) calloc(3*total_data, sizeof(double))) == NULL) OutOfMemory(); if ((ica_signal = (double *) calloc(3*total_data, sizeof(double))) == NULL) OutOfMemory(); // HR - Copy red, green, and blue signal into input_ica int index = 0; for (int j = 0; j < total_data; j++){ ica_signal[index] = XinT.at(0,j)[0]; ica_signal[index+1] = XinT.at(0,j)[1]; ica_signal[index+2] = XinT.at(0,j)[2]; index += 3; } // HR - ICA Jade Jade(ica_matrix, ica_signal, 3, total_data); // HR - Copy ICA result into InputFFTCx index = 0; Mat InputFFTC1(1, fft_size, CV_64F, cv::Scalar(0)); Mat InputFFTC2(1, fft_size, CV_64F, cv::Scalar(0)); Mat InputFFTC3(1, fft_size, CV_64F, cv::Scalar(0)); for (int j = 0; j < total_data; j++){ InputFFTC1.at(j) = ica_signal[index]; InputFFTC2.at(j) = ica_signal[index+1]; InputFFTC3.at(j) = ica_signal[index+2]; index += 3; } // HR - Free memory of input_ica and output_ica free(ica_matrix); free(ica_signal); // HR - Get FFT result magnitude from 1st component Mat planes1[] = {Mat_(InputFFTC1), Mat::zeros(InputFFTC1.size(), CV_64F)}; Mat complexI1; merge(planes1, 2, complexI1); // Add to the expanded another plane with zeros dft(complexI1, complexI1); // this way the result may fit in the source matrix split(complexI1, planes1); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) magnitude(planes1[0], planes1[1], planes1[0]); // planes[0] = magnitude Mat MagnitudeC1 = planes1[0]; // HR - Get FFT result magnitude from 2nd component Mat planes2[] = {Mat_(InputFFTC2), Mat::zeros(InputFFTC2.size(), CV_64F)}; Mat complexI2; merge(planes2, 2, complexI2); // Add to the expanded another plane with zeros dft(complexI2, complexI2); // this way the result may fit in the source matrix split(complexI2, planes2); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) magnitude(planes2[0], planes2[1], planes2[0]); // planes[0] = magnitude Mat MagnitudeC2 = planes2[0]; // HR - Get FFT result magnitude from 3rd component Mat planes3[] = {Mat_(InputFFTC3), Mat::zeros(InputFFTC3.size(), CV_64F)}; Mat complexI3; merge(planes3, 2, complexI3); // Add to the expanded another plane with zeros dft(complexI3, complexI3); // this way the result may fit in the source matrix split(complexI3, planes3); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) magnitude(planes3[0], planes3[1], planes3[0]); // planes[0] = magnitude Mat MagnitudeC3 = planes3[0]; /// HR4. Get Power Spectrum // HR - Get power spectrum from FFT result Mat PowerSpectrumR(1, hr_max, CV_64F); Mat PowerSpectrumG(1, hr_max, CV_64F); Mat PowerSpectrumB(1, hr_max, CV_64F); Mat PowerSpectrumC1(1, hr_max, CV_64F); Mat PowerSpectrumC2(1, hr_max, CV_64F); Mat PowerSpectrumC3(1, hr_max, CV_64F); for (int j = 0; j < hr_max; j++){ PowerSpectrumR.at(j) = MagnitudeR.at(j)*MagnitudeR.at(j); PowerSpectrumG.at(j) = MagnitudeG.at(j)*MagnitudeG.at(j); PowerSpectrumB.at(j) = MagnitudeB.at(j)*MagnitudeB.at(j); PowerSpectrumC1.at(j) = MagnitudeC1.at(j)*MagnitudeC1.at(j); PowerSpectrumC2.at(j) = MagnitudeC2.at(j)*MagnitudeC2.at(j); PowerSpectrumC3.at(j) = MagnitudeC3.at(j)*MagnitudeC3.at(j); } /// HR5. Get Heart Rate // HR - Searching for frequency with highest power spectrum double power_temp_r_1 = 0, power_temp_g_1 = 0, power_temp_b_1 = 0; double power_temp_c1_1 = 0, power_temp_c2_1 = 0, power_temp_c3_1 = 0; double power_temp_r_2 = 0, power_temp_g_2 = 0, power_temp_b_2 = 0; double power_temp_c1_2 = 0, power_temp_c2_2 = 0, power_temp_c3_2 = 0; for (int j = hr_min; j < hr_max - 1; j++){ // red signal if ((PowerSpectrumR.at(j) > PowerSpectrumR.at(j+1)) && (PowerSpectrumR.at(j) > PowerSpectrumR.at(j-1))) { if (PowerSpectrumR.at(j) > power_temp_r_1){ power_temp_r_2 = power_temp_r_1; power_temp_r_1 = PowerSpectrumR.at(j); heart_rate_r_2 = heart_rate_r_1; heart_rate_r_1 = j; } else if (PowerSpectrumR.at(j) > power_temp_r_2) { power_temp_r_2 = PowerSpectrumR.at(j); heart_rate_r_2 = j; } } // green signal if ((PowerSpectrumG.at(j) > PowerSpectrumG.at(j+1)) && (PowerSpectrumG.at(j) > PowerSpectrumG.at(j-1))) { if (PowerSpectrumG.at(j) > power_temp_g_1){ power_temp_g_2 = power_temp_g_1; power_temp_g_1 = PowerSpectrumG.at(j); heart_rate_g_2 = heart_rate_g_1; heart_rate_g_1 = j; } else if (PowerSpectrumG.at(j) > power_temp_g_2) { power_temp_g_2 = PowerSpectrumG.at(j); heart_rate_g_2 = j; } } // blue signal if ((PowerSpectrumB.at(j) > PowerSpectrumB.at(j+1)) && (PowerSpectrumB.at(j) > PowerSpectrumB.at(j-1))) { if (PowerSpectrumB.at(j) > power_temp_b_1){ power_temp_b_2 = power_temp_b_1; power_temp_b_1 = PowerSpectrumB.at(j); heart_rate_b_2 = heart_rate_b_1; heart_rate_b_1 = j; } else if (PowerSpectrumB.at(j) > power_temp_b_2) { power_temp_b_2 = PowerSpectrumB.at(j); heart_rate_b_2 = j; } } // 1st component if ((PowerSpectrumC1.at(j) > PowerSpectrumC1.at(j+1)) && (PowerSpectrumC1.at(j) > PowerSpectrumC1.at(j-1))) { if (PowerSpectrumC1.at(j) > power_temp_c1_1){ power_temp_c1_2 = power_temp_c1_1; power_temp_c1_1 = PowerSpectrumC1.at(j); heart_rate_c1_2 = heart_rate_c1_1; heart_rate_c1_1 = j; } else if (PowerSpectrumC1.at(j) > power_temp_c1_2) { power_temp_c1_2 = PowerSpectrumC1.at(j); heart_rate_c1_2 = j; } } // 2nd component if ((PowerSpectrumC2.at(j) > PowerSpectrumC2.at(j+1)) && (PowerSpectrumC2.at(j) > PowerSpectrumC2.at(j-1))) { if (PowerSpectrumC2.at(j) > power_temp_c2_1){ power_temp_c2_2 = power_temp_c2_1; power_temp_c2_1 = PowerSpectrumC2.at(j); heart_rate_c2_2 = heart_rate_c2_1; heart_rate_c2_1 = j; } else if (PowerSpectrumC2.at(j) > power_temp_c2_2) { power_temp_c2_2 = PowerSpectrumC2.at(j); heart_rate_c2_2 = j; } } // 3rd component if ((PowerSpectrumC3.at(j) > PowerSpectrumC3.at(j+1)) && (PowerSpectrumC3.at(j) > PowerSpectrumC3.at(j-1))) { if (PowerSpectrumC3.at(j) > power_temp_c3_1){ power_temp_c3_2 = power_temp_c3_1; power_temp_c3_1 = PowerSpectrumC3.at(j); heart_rate_c3_2 = heart_rate_c3_1; heart_rate_c3_1 = j; } else if (PowerSpectrumC3.at(j) > power_temp_c3_2) { power_temp_c3_2 = PowerSpectrumC3.at(j); heart_rate_c3_2 = j; } } } // HR - Copy heart rate component in to HRVec int previous_heart_rate = heart_rate; bool hr_found = false; vectorHRVec(6); if ((heart_rate_c2_1 < hr_good_max) && (heart_rate_c2_1 > hr_good_min)) { HRVec[0] = heart_rate_c2_1; heart_rate = heart_rate_c2_1; heart_rate_c = 2; hr_found = true; } else { HRVec[0] = 0; } if ((heart_rate_c2_2 < hr_good_max) && (heart_rate_c2_2 > hr_good_min)) { HRVec[1] = heart_rate_c2_2; if (!hr_found) { heart_rate = heart_rate_c2_2; heart_rate_c = 2; hr_found = true; } } else { HRVec[1] = 0; } if ((heart_rate_c1_1 < hr_good_max) && (heart_rate_c1_1 > hr_good_min)) { HRVec[2] = heart_rate_c1_1; if (!hr_found) { heart_rate = heart_rate_c1_1; heart_rate_c = 1; hr_found = true; } } else { HRVec[2] = 0; } if ((heart_rate_c1_2 < hr_good_max) && (heart_rate_c1_2 > hr_good_min)) { HRVec[3] = heart_rate_c1_2; if (!hr_found) { heart_rate = heart_rate_c1_2; heart_rate_c = 1; hr_found = true; } } else { HRVec[3] = 0; } if ((heart_rate_c3_1 < hr_good_max) && (heart_rate_c3_1 > hr_good_min)) { HRVec[4] = heart_rate_c3_1; if (!hr_found) { heart_rate = heart_rate_c3_1; heart_rate_c = 3; hr_found = true; } } else { HRVec[4] = 0; } if ((heart_rate_c3_2 < hr_good_max) && (heart_rate_c3_2 > hr_good_min)) { HRVec[5] = heart_rate_c3_2; if (!hr_found) { heart_rate = heart_rate_c3_2; heart_rate_c = 3; hr_found = true; } } else { HRVec[5] = 0; } // HR - Select the nearest heart rate from previous heart rate int heart_rate_diff = 240; if (previous_heart_rate > 0) { if ((Absolute(HRVec[0] - previous_heart_rate) < 13)) { if ((Absolute(HRVec[0] - previous_heart_rate) < heart_rate_diff)) { heart_rate = HRVec[0]; heart_rate_c = 2; heart_rate_diff = Absolute(HRVec[0] - previous_heart_rate); } } if ((Absolute(HRVec[1] - previous_heart_rate) < 13)) { if ((Absolute(HRVec[1] - previous_heart_rate) < heart_rate_diff)) { heart_rate = HRVec[1]; heart_rate_c = 2; heart_rate_diff = Absolute(HRVec[1] - previous_heart_rate); } } if ((Absolute(HRVec[2] - previous_heart_rate) < 13)) { if ((Absolute(HRVec[2] - previous_heart_rate) < heart_rate_diff)) { heart_rate = HRVec[2]; heart_rate_c = 1; heart_rate_diff = Absolute(HRVec[2] - previous_heart_rate); } } if ((Absolute(HRVec[3] - previous_heart_rate) < 13)) { if ((Absolute(HRVec[3] - previous_heart_rate) < heart_rate_diff)) { heart_rate = HRVec[3]; heart_rate_c = 1; heart_rate_diff = Absolute(HRVec[3] - previous_heart_rate); } } if ((Absolute(HRVec[4] - previous_heart_rate) < 13)) { if ((Absolute(HRVec[4] - previous_heart_rate) < heart_rate_diff)) { heart_rate = HRVec[4]; heart_rate_c = 3; heart_rate_diff = Absolute(HRVec[4] - previous_heart_rate); } } if ((Absolute(HRVec[5] - previous_heart_rate) < 13)) { if ((Absolute(HRVec[5] - previous_heart_rate) < heart_rate_diff)) { heart_rate = HRVec[5]; heart_rate_c = 3; heart_rate_diff = Absolute(HRVec[5] - previous_heart_rate); } } } /** Get Body Temperature **/ body_temperature = GetBT(); /** Save Result **/ if (log_on) { n_result++; if (n_result == 1) { LogCreate(); } LogWrite(); } /** Display Result **/ if (gui_new) { // Display HR, RR, and BT Display = Scalar(0); putText(Display, "HR", Point(50,300), 0, 5, Scalar(255), 5); putText(Display, "RR", Point(500,300), 0, 5, Scalar(255), 5); putText(Display, "BT", Point(950,300), 0, 5, Scalar(255), 5); // HR - Display heart rate result stringstream TextOut1; if ((heart_rate > hr_max) || (heart_rate < hr_min)) { // HR is not in the valid range TextOut1<<"-"; putText(Display, TextOut1.str(), Point(50,500), 0, 5, Scalar(255), 5); if (speak_on) { imshow(DisplayWindow, Display); // show display waitKey(1); } } else { // HR is in the valid range TextOut1< rr_max) || (respiration_rate < rr_min)) { // RR is not in the valid range TextOut2<<"-"; putText(Display, TextOut2.str(), Point(500,500), 0, 5, Scalar(255), 5); if (speak_on) { imshow(DisplayWindow, Display); // show display waitKey(1); } } else { // RR is in the valid range TextOut2< bt_max) || (body_temperature < bt_min)) { // BT is not in the valid range TextOut3<<"-"; putText(Display, TextOut3.str(), Point(950,500), 0, 5, Scalar(255), 5); if (speak_on) { imshow(DisplayWindow, Display); // show display waitKey(1); } } else { // BT is in the valid range TextOut3<(j)), Point(2*j+2, 150-PowerSpectrumR.at(j+1)), Scalar(200,200,200), 2, 8, 0); line(DrawHRPSG, Point(2*j, 150-PowerSpectrumG.at(j)), Point(2*j+2, 150-PowerSpectrumG.at(j+1)), Scalar(200,200,200), 2, 8, 0); line(DrawHRPSB, Point(2*j, 150-PowerSpectrumB.at(j)), Point(2*j+2, 150-PowerSpectrumB.at(j+1)), Scalar(200,200,200), 2, 8, 0); line(DrawHRPSC1, Point(2*j, 150-PowerSpectrumC1.at(j)), Point(2*j+2, 150-PowerSpectrumC1.at(j+1)), Scalar(200,200,200), 2, 8, 0); line(DrawHRPSC2, Point(2*j, 150-PowerSpectrumC2.at(j)), Point(2*j+2, 150-PowerSpectrumC2.at(j+1)), Scalar(200,200,200), 2, 8, 0); line(DrawHRPSC3, Point(2*j, 150-PowerSpectrumC3.at(j)), Point(2*j+2, 150-PowerSpectrumC3.at(j+1)), Scalar(200,200,200), 2, 8, 0); } for (int j = hr_min; j < (hr_max - 1); j++){ line(DrawHRPSR, Point(2*j, 150-PowerSpectrumR.at(j)), Point(2*j+2, 150-PowerSpectrumR.at(j+1)), Scalar(0,0,200), 2, 8, 0); line(DrawHRPSG, Point(2*j, 150-PowerSpectrumG.at(j)), Point(2*j+2, 150-PowerSpectrumG.at(j+1)), Scalar(0,200,0), 2, 8, 0); line(DrawHRPSB, Point(2*j, 150-PowerSpectrumB.at(j)), Point(2*j+2, 150-PowerSpectrumB.at(j+1)), Scalar(200,0,0), 2, 8, 0); line(DrawHRPSC1, Point(2*j, 150-PowerSpectrumC1.at(j)), Point(2*j+2, 150-PowerSpectrumC1.at(j+1)), Scalar(140,90,60), 2, 8, 0); line(DrawHRPSC2, Point(2*j, 150-PowerSpectrumC2.at(j)), Point(2*j+2, 150-PowerSpectrumC2.at(j+1)), Scalar(130,80,70), 2, 8, 0); line(DrawHRPSC3, Point(2*j, 150-PowerSpectrumC3.at(j)), Point(2*j+2, 150-PowerSpectrumC3.at(j+1)), Scalar(120,100,50), 2, 8, 0); } // HR - Show heart rate on heart rate power spectrum stringstream TextOutR; TextOutR<(j)), Point(j+1, 150-SmoothenData.at(j+1)), Scalar(0,0,0), 2, 8, 0); } // RR - Normalize PowerSpectrumRR to range 0 to 150, image matrix type is CV_8UC3 minVal, maxVal; minMaxLoc(PowerSpectrumRR, &minVal, &maxVal); dividen = 150/(maxVal-minVal); offset = -minVal; PowerSpectrumRR.convertTo(PowerSpectrumRR, CV_8U, dividen, offset); // RR - Whitening DrawRRPS image DrawRRPS = Scalar(255, 255, 255); // RR - Draw power spectrum of respiration rate in DrawRRPS for (int j = 1; j < (rr_max - 1); j++) { line(DrawRRPS, Point(2*j, 150-PowerSpectrumRR.at(j)), Point(2*j+2, 150-PowerSpectrumRR.at(j+1)), Scalar(0,255,0), 2, 8, 0); } } } /** Send Data To Database Server **/ if (send_to_database) { WSADATA WsaDat; if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0) { std::cout<<"Winsock error - Winsock Initialization failed\r\n"; WSACleanup(); } // Create our socket Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(Socket==INVALID_SOCKET) { std::cout<<"Winsock error - Socket creation Failed!\r\n"; WSACleanup(); } // Resolve IP address for hostname struct hostent *host; if((host=gethostbyname(host_name))==NULL) { std::cout<<"Failed to resolve hostname.\r\n"; WSACleanup(); } // Setup our socket address structure SockAddr.sin_port=htons(port_number); SockAddr.sin_family=AF_INET; SockAddr.sin_addr.s_addr=*((unsigned long*)host->h_addr); // Attempt to connect to server if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr))!=0) { std::cout<<"Failed to establish connection with server\r\n"; WSACleanup(); } // Compiling estimated value into 1 string message sprintf(message, "%d:%d:%.1f\n", heart_rate, respiration_rate, body_temperature); // Send compiled message to database send(Socket, message, strlen(message), 0); // Shutdown our socket shutdown(Socket,SD_SEND); // Close our socket entirely closesocket(Socket); // Cleanup winsock WSACleanup(); } /** Restart Measurement **/ // Set iterator -1 i = -1; // Set validiy true validity = true; } // Increase iterator i++; } else { // face undetected if (count_down < 0) { // Increase count down count_down++; } // Restart measurement i = start_iterator; validity = true; } // Show images if (gui_new) { imshow(DisplayWindow, Display); // show display } else { // old GUI imshow(FrameWindow, Frame); // show frame imshow(ResultWindow, DrawResult); // show result if (debug_information) { imshow("1st Component", DrawHRPSC1); // show power spectrum of 1st component of heart rate imshow("2nd Component", DrawHRPSC2); // show power spectrum of 2nd component of heart rate imshow("3rd Component", DrawHRPSC3); // show power spectrum of 3rd component of heart rate imshow("Red Component", DrawHRPSR); // show power spectrum of red component of heart rate imshow("Green Component", DrawHRPSG); // show power spectrum of green component of heart rate imshow("Blue Component", DrawHRPSB); // show power spectrum of blue component of heart rate imshow("Respiration Signal", DrawRRSignal); // show respiration signal imshow("RR Power Spectrum", DrawRRPS); // show power spectrum of respiration rate } } // RR - Change current and previous current = (current+1)%total_frame; previous = (previous+1)%total_frame; // Calculate duration of process duration = static_cast(getTickCount())-duration; duration /= getTickFrequency(); // elapsed time in second // Show debug information printf("frame %dx%d rate %d f %d c %d ", Frame.cols, Frame.rows, frame_rate, Faces.size(), count_down); if (face_detected) { printf("i %d t %1.3f s face %dx%d\n", i, duration, TempFace.width, TempFace.height); } else { printf("t %1.3f s\n", duration); } // Introduce delay or press any key to stop (delay replace with 1 when slow processing time) int delay = sampling_periode - (duration*1000) - 1; if (delay < 1) { delay = 1; if ((i >= 0) && (i <= total_data)) { validity = false; cout<<" :("<= 0) || finish) { break; } } // Close the video, not required since called by destructor Capture.release(); // Close log file if (log_on) { LogClose(); } return 0; } Share: Facebook Twitter Google+ StumbleUpon Digg Delicious LinkedIn Reddit Technorati
0 komentar:
Posting Komentar