diff --git a/chroma/src/chroma.cpp b/chroma/src/chroma.cpp index e547990..4bf5a2d 100644 --- a/chroma/src/chroma.cpp +++ b/chroma/src/chroma.cpp @@ -95,7 +95,7 @@ void Chroma_processing::imageCb(const sensor_msgs::ImageConstPtr& msg) //Blob detection if(display) { - detectBlobs(dif_rgb, rgb_rects, 15); + detectBlobs(dif_rgb, rgb_rects, 15, true); Mat temp = dif_rgb.clone(); for(Rect rect: rgb_rects) diff --git a/fusion/CMakeLists.txt b/fusion/CMakeLists.txt index 3a9d6d3..90417e5 100644 --- a/fusion/CMakeLists.txt +++ b/fusion/CMakeLists.txt @@ -40,7 +40,6 @@ aux_source_directory(src/ SRC_LIST) include_directories( include /usr/include/ - /usr/include/libalglib/ ${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} diff --git a/fusion/include/fusion.hpp b/fusion/include/fusion.hpp index 4e02ff4..72c9269 100644 --- a/fusion/include/fusion.hpp +++ b/fusion/include/fusion.hpp @@ -26,7 +26,6 @@ using namespace std; using namespace cv; -using namespace alglib; #define DEPTH_MAX 6000.0 /**< Default maximum distance. Only use this for initialization. */ #define DEPTH_MIN 0.0 /**< Default minimum distance. Only use this for initialization. */ diff --git a/fusion/src/fusion.cpp b/fusion/src/fusion.cpp index 1e5138f..06a7301 100644 --- a/fusion/src/fusion.cpp +++ b/fusion/src/fusion.cpp @@ -84,7 +84,7 @@ void Fusion_processing::callback(const sensor_msgs::ImageConstPtr& chroma_msg, c cv::threshold(fusion, fusion, 100, 255, THRESH_BINARY); //Detect moving blobs - detectBlobs(fusion, fusion_rects, 15); + detectBlobs(fusion, fusion_rects, 15, true); //Track blobs track(fusion_rects, people); diff --git a/vision/CMakeLists.txt b/vision/CMakeLists.txt index fd5daab..eee6f37 100644 --- a/vision/CMakeLists.txt +++ b/vision/CMakeLists.txt @@ -12,7 +12,6 @@ catkin_package(INCLUDE_DIRS include include_directories( include /usr/include/ - /usr/include/libalglib/ ${OpenCV_INCLUDE_DIRS} ) @@ -30,7 +29,6 @@ add_library(vision SHARED ${SOURCES}) target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} - alglib ) install(DIRECTORY include/${PROJECT_NAME}/ diff --git a/vision/include/vision.hpp b/vision/include/vision.hpp index b5b1623..34010b9 100644 --- a/vision/include/vision.hpp +++ b/vision/include/vision.hpp @@ -13,13 +13,9 @@ #include #include -#include -#include - - using namespace std; - using namespace cv; - using namespace alglib; +using namespace std; +using namespace cv; @@ -41,7 +37,7 @@ }; //Detection and tracking of blobs - void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range); + void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range, bool detect_people); void track(vector< Rect_ >& current, People& collection, int rank = 3, float threshold = 0.2); //Depth estimation functions @@ -71,7 +67,6 @@ void fixRects(vector< Rect_ >& rects, int screenW); void depthToGray(Mat& src, Mat& dst, float min_depth, float max_depth); void grayToDepth(Mat& src, Mat& dst, float max_depth); - kmeansreport clusterize(const vector& vec, int clusters); #endif diff --git a/vision/src/depth_methods.cpp b/vision/src/depth_methods.cpp new file mode 100644 index 0000000..da14832 --- /dev/null +++ b/vision/src/depth_methods.cpp @@ -0,0 +1,871 @@ +#include + +/*Converts a grayscale Mat to a depth Mat by using the maximum depth value + * + * PARAMETERS: + * -Mat depth + * -Mat with the graysclae result + * -float minimum depth + * -float maximum depth + * + * RETURN: -- + */ +void grayToDepth(Mat& src, Mat& dst, float max_depth) +{ + Mat temp_img(src.rows, src.cols, CV_32FC1); + int cols = src.cols; + int rows = src.rows; + if(src.isContinuous()) + { + cols *= rows; + rows = 1; + } + for(int i = 0; i < rows; i++) + { + uchar* cur = src.ptr(i); + float* Ii = temp_img.ptr(i); + for(int j = 0; j < cols; j++) + { + Ii[j] = (max_depth*(float(cur[j])/(255.0))); + } + } + dst = temp_img.clone(); + +} + +/*Converts a depth Mat to a grayscale one by using the min and maximum depth values + * + * PARAMETERS: + * -Mat depth + * -Mat with the graysclae result + * -float minimum depth + * -float maximum depth + * + * RETURN: -- + */ +void depthToGray(Mat& src, Mat& dst, float min_depth, float max_depth) +{ + + Mat temp_img(src.rows, src.cols, CV_8UC1); + int cols = src.cols; + int rows = src.rows; + if(src.isContinuous()) + { + cols *= rows; + rows = 1; + } + for(int i = 0; i < rows; i++) + { + float* cur = src.ptr(i); + uchar* Ii = temp_img.ptr(i); + for(int j = 0; j < cols; j++) + { + Ii[j] = (255*((cur[j] - min_depth)/(max_depth - min_depth))); + } + } + dst = temp_img.clone(); + +} + +/* Calculates the depth of the closest object in the specified Mat by using clustering + * + * PARAMETERS: + * -Mat + * -number of values to calculate + * + * RETURN: + * -Double holding the min cluster median value + * + */ +double calculateDepth(Mat& src, Rect_ personRect) +{ + + int clusters = 2; + int cols = src.cols; + int rows = src.rows; + int channels = src.channels(); + int size = cols*rows*channels; + double median = 0.0; + double saveMin = 0.0; + double saveCluster = 0.0; + double saveCenter = 0.0; + double depthCombined = 0.0; + vector vec; + vector cluster_vec; + Mat labels; + Mat centers; + + if(cols > 0 && rows > 0) + { + + if(src.isContinuous()) + { + rows = 1; + cols = size; + } + + cols = src.cols*0.7; + rows = src.rows*0.4; + + for(int i = 0; i < rows; i++) + { + const float* cur = src.ptr(i); + for(int j = 0; j < cols; j++) + { + cluster_vec.push_back(cur[j]); + + } + + } + double compact = kmeans(cluster_vec, clusters, labels, TermCriteria(TermCriteria::EPS+TermCriteria::COUNT, 10, 1.0), 3, KMEANS_PP_CENTERS, centers); + + // cluster item count + int counter[clusters]; + for(int i = 0; i < clusters; i++) + { + counter[i] = 0; + } + + //check which centroid has the smallest value + int min_centroid = INT_MAX; + int index [clusters + 1]; + for(int i = 0; i < clusters + 1; i++) + { + index[i] = -1; + } + + if(centers.rows > 0) + { + for(int i = 0; i < clusters; i++) + { + if((min_centroid > centers.at(i)) && (centers.at(i) > 0)) + { + min_centroid = centers.at(i); + index[0] = i; + } + } + index[index[0] + 1] = INT_MAX; + + //cout<(i); + for(int j = 0; j < cols; j++) + { + if(index[0] == labels.at(i*cols + j)) + { + cluster_vec.push_back(cur[j]); + } + } + } + + //median + nth_element(cluster_vec.begin(), cluster_vec.begin() + cluster_vec.size()/2, cluster_vec.end()); + median = cluster_vec[cluster_vec.size()/2]; + for(int i = 1; i < clusters + 1; i++) + { + if(index[i] == -1) + { + index[0] = i - 1; + index[i] = INT_MAX; + break; + } + } + } + + //~ printf("%s %2.3f\n","Depth: " ,median); + + /* + Mat src_gray; + depthToGray(src, src_gray, 0, max_depth); + for(int i = 0; i < rows; i++) + { + uchar* cur = src_gray.ptr(i); + for(int j = 0; j < cols; j++) + { + if(rep.cidx[i*cols + j] == index[0]) + { + cur[j] = 0; + } + else + { + cur[j] = 255; + } + } + } + + Mat temp_img(height, depth_width, CV_8UC1); + temp_img = Scalar(0); + + src.copyTo(temp_img(Rect(personRect.x, personRect.y, cols, rows))); + imshow("Clustered", temp_img); + moveWindow("Clustered", 645, 0); + */ + + } + + } + return median; + + + /* + // Preprocessing step to discard null or unwanted depth values + // and convert Mat to vector + for(int i = 0; i < rows; i++) + { + float* cur = src.ptr(i); + for(int j = 0; j < cols; j++) + { + vec.push_back(cur[j]); + } + + } + // average of minimum vector elements + saveMin = minDepth(vec, 20); + + // find the depth of the mat center area + saveCenter = centerDepth(src, 10); + + + + + //~ int id = -1; + //~ double result = FLT_MAX; + //~ + //~ for(int i = 0; i < rep.c.rows() - 1; i++) + //~ { + //~ double temp = std::min(result, rep.c[i + 1][0]); + //~ if(temp > 0) + //~ { + //~ id = i; + //~ result = temp; + //~ } + //~ } + //~ saveCluster = result; + + //combine the results of the 2 closest + depthCombined = combineDepth(saveMin, saveCenter, median, 0, max_depth); + + + //~ printf("%s %2.3f\n","Depth combined: " ,depthCombined); + return depthCombined; + */ + +} + +/* Finds an average of the minimum + * values of a given vector + * + * PARAMETERS: + * -vector with the values + * -number of values to calculate + * + * RETURN: + * -Double holding the average value + * + */ +double minDepth(vector vec, int number) +{ + double result = 0; + double min = 0; + int done = 0; + float threshold = number; + partial_sort (vec.begin(), vec.begin() + threshold, vec.end()); + for(int i = 0; i < threshold; i++) + { + result += vec.at(i); + } + result = result/threshold; + cout<<"Save Min: "<(src.rows/2 - number/2 + i, src.cols/2 - number/2 + j); + if(std::isnan(temp) || temp == FLT_MAX) + continue; + result += temp; + counter++; + } + } + + cout<<"Save Center: "< max_depth) + //~ { + //~ return FLT_MAX; + //~ } + return result/counter; +} + +/* Calculates an average of the 2 closest values + * + * PARAMETERS: + * -Double the min depth approximation + * -Double the center depth approximation + * -Double the cluster depth approximation + * + * + * RETURN: + * -Double holding the average of the 2 closest values + */ +double combineDepth(double saveMin, double saveCenter, double saveCluster, double min_depth, double max_depth) +{ + double result; + double minClusterDif; + double minCenterDif; + double clusterCenterDif; + + + + + if((saveMin == FLT_MAX || saveMin == 0) && (saveCluster == FLT_MAX || saveCluster == 0)) + minClusterDif = FLT_MAX; + else + minClusterDif = abs(saveMin - saveCluster); + + if((saveMin == FLT_MAX || saveMin == 0) && (saveCenter == FLT_MAX || saveCenter == 0)) + minCenterDif = FLT_MAX; + else + minCenterDif = abs(saveMin - saveCenter); + + if((saveCluster == FLT_MAX || saveCluster == 0) && (saveCenter == FLT_MAX || saveCenter == 0)) + clusterCenterDif = FLT_MAX; + else + clusterCenterDif = abs(saveCluster - saveCenter); + + + if(minClusterDif > max_depth/10) + minClusterDif = FLT_MAX; + if(minCenterDif > max_depth/10) + minCenterDif = FLT_MAX; + if(clusterCenterDif > max_depth/10) + clusterCenterDif = FLT_MAX; + + if(minClusterDif < minCenterDif) + { + if(minClusterDif < clusterCenterDif) + result = (saveMin + saveCluster)/2; + else + result = (saveCluster + saveCenter)/2; + } + else if(minCenterDif < clusterCenterDif) + result = (saveMin + saveCenter )/2; + else if(clusterCenterDif < minClusterDif) + result = (saveCenter + saveCluster)/2; + else + { + result = max(saveMin, saveCenter); + result = max(result, saveCluster); + } + + + return result; +} + +/*Region growing algorithm that fills black holes in the depth image, uses + * rectangular areas + * + * PARAMETERS: + * -Mat to be corrected + * -float threshold of correction + * -int range of each correctin area + * + * RETURN: -- + */ +void rectFill(Mat& src, float threshold, int range) +{ + uchar *cur, *temp,*vFill; + int channels = src.channels(); + int cols = src.cols; + int rows = src.rows; + int size = cols*rows*channels; + int count = 0; + float all = 0.0; + float bPercent = 0.0; + float gPercent = 0.0; + float rPercent = 0.0; + bool has_zero = false; + bool flag = false; + + for(int y = 0; y < 1; y++) + { + cur = src.ptr(y); + for(int x = channels*range + cols*range; x < size - (channels*range + cols*range); x = x + channels) + { + if ((cur[x] != 0 && channels == 1) || (channels > 1 && (cur[x+1] != 0 || cur[x+2] != 0) )) + { + int top = x - range*cols*channels; + int topLeft = top - range*channels; + int topRight = top + range*cols*channels; + int bottom = x + range*cols*channels; + int bottomLeft = bottom - range*cols*channels; + int bottomRight = bottom + range*cols*channels; + + if(topLeft%(cols*channels) > top%(cols*channels)) + continue; + if(topRight%(cols*channels) < top%(cols*channels)) + continue; + + has_zero = false; + flag = false; + count = 0; + for(int a = topLeft; a < bottomLeft; a = a + cols*channels) + { + for(int b = a; b < a + 2*range*channels ; b += channels) + { + if (cur[b] == 0) + { + has_zero = true; + count++; + } + else + { + if(channels == 1) + { + all = abs( (float(cur[b])/255) - (float(cur[x])/255) ); + if(all >= threshold) + flag = true; + } + } + + } + } + int countThresh = range; + if(!flag && has_zero && (count <= countThresh)) + { + for(int a = topLeft; a < bottomLeft; a = a + cols*channels) + { + for(int b = a; b < a + 2*range*channels ; b += channels) + { + if (cur[b] == 0) + { + cur[b] = cur[x]; + } + } + } + } + //~ x = x - range*channels + channels; + } + } + } +} + +/* Fills the black holes in the Mat horizontally + * + * PARAMETERS: + * -the Mat to be processed + * -the comparison threshold + * + * RETURN: -- + * + */ +void rightHorizontalFill(Mat& cur_Mat, float threshold, bool scale) +{ + uchar *cur; + int channels = cur_Mat.channels(); + int cols = cur_Mat.cols; + int rows = cur_Mat.rows; + int size = cols*rows*channels; + float all = 0.0, bPercent = 0.0, gPercent = 0.0, rPercent = 0.0; + + for(int y = 0; y < 1; y++) + { + cur = cur_Mat.ptr(y); + for(int x = 0; x < size; x = x + channels) + { + /*If it is the end of the current line, continue*/ + if(x > 0 && (x%(cols*channels) == 0 || x%(cols*channels) == (cols - 1))) + continue; + if(cur[x] != 0 && ((cur[x + channels] == 0 && channels == 1) || (channels > 1 && (cur[x+1] != 0 | cur[x+2] != 0) ))) + { + int start = x + 2*channels; + for(int a = start; a < size; a = a + channels) + { + //check not to change line + if((x%(cols*channels)) > (a%(cols*channels))) + break; + if(cur[a] != 0) + { + if(channels == 1) + { + all = abs( (float(cur[a])/255) - (float(cur[x])/255) ); + if(all < threshold) + { + if(scale) + { + int rowA = a%(cols*channels); + int rowX = x%(cols*channels); + all = (all/abs(rowA - rowX))*255; + int ratio = 1; + for(int i = x + channels; i < a; i = i + channels) + { + cur[i] = cur[x] + ratio*all; + ratio++; + } + } + else + { + for(int i = x + channels; i < a; i = i + channels) + cur[i] = (cur[x] + cur[a])/2; + } + } + } + else if(cur[a + 1] == 0 && cur[a + 2] == 0) + { + + + bPercent = abs( (double(cur[a])/255) - (double(cur[x])/255) ); + gPercent = abs( (double(cur[a + 1])/255) - (double(cur[x + 1])/255) ); + rPercent = abs( (double(cur[a + 2])/255) - (double(cur[x + 2])/255) ); + + all = bPercent + gPercent + rPercent; + + if(all < threshold){ + cur[a] = cur[x]; + cur[a+1] = cur[x+1]; + cur[a+2] = cur[x+2]; + } + else + break; + } + break; + } + } + } + } + } +} + +/* Fills the black holes in the Mat vertically + * from bottom to top + * + * @param the Mat to be processed, the comparison threshold + * @return - + * + */ +void upVerticalFill(Mat& src, float threshold, bool flag) +{ + uchar *cur; + int channels = src.channels(); + int cols = src.cols; + int rows = src.rows; + int size = cols*rows*channels; + float all = 0.0; + float bPercent = 0.0; + float gPercent = 0.0; + float rPercent = 0.0; + + threshold *= 255; + float threshold2 = 0.01*255; + for(int y = 0; y < 1; y++) + { + cur = src.ptr(y); + for(int x = size; x > cols*channels; x = x - channels) + { + + if(int(cur[x]) != 0 && ((int(cur[x - cols*channels]) == 0 && channels == 1) || (channels > 1 && (cur[x+1] != 0 | cur[x+2] != 0) ))) + { + + int start = ((x - 2*cols*channels) > 0)?(x - 2*cols*channels):0; + //~ int end = ((start + cols*verRange) < size)?(start + cols*verRange):size; + + for(int a = start; a > 0 ; a = a - cols*channels) + { + if((x - a)/(cols*channels) > rows/10) + { + break; + } + if(int(cur[a]) != 0) + { + if(channels == 1) + { + all = abs(int(cur[a]) - int(cur[x])); + if(all < threshold) + { + int ratio = 1; + int rowA = floor(a/(cols*channels)); + int rowX = floor(x/(cols*channels)); + int color = int(cur[x]) - int(cur[a]); + color /= abs(rowA - rowX); + + for(int i = x - cols*channels; i > a; i = i - cols*channels) + { + cur[i] = int(cur[x]) - ratio*color; + ratio++; + } + } + else + { + for(int i = x - cols*channels; i > a; i = i - cols*channels) + { + int left = 0; + int right = 0; + for(int j = i; j < size ; j = j + channels) + { + //check not to change line + if((i%(cols*channels)) > (j%(cols*channels))) + break; + if(cur[j] != 0) + { + if(channels == 1) + { + right = j; + } + break; + } + } + for(int j = i; j > 0 ; j = j - channels) + { + //check not to change line + if((i%(cols*channels)) < (j%(cols*channels))) + break; + if(cur[j] != 0) + { + if(channels == 1) + { + left = j; + } + break; + } + } + if(!flag) + { + if((abs(int(cur[x]) - int(cur[left])) < threshold)) + { + cur[i] = int(cur[left]) - (int(cur[left]) - int(cur[x]))/abs(left - x); + } + else if((abs(int(cur[x]) - int(cur[right])) < threshold)) + { + cur[i] = int(cur[right]) - (int(cur[right]) - int(cur[x]))/abs(right - x); + } + } + else + { + //~ if(abs(int(cur[left]) - int(cur[right])) < threshold) + //~ { + cur[i] = int(cur[x]); + //~ } + } + //~ else + //~ { + //~ cur[i] = int(cur[a]); + //~ } + } + } + } + else if(cur[a + 1] == 0 && cur[a + 2] == 0) + { + bPercent = abs(cur[a] - cur[x]); + gPercent = abs(cur[a + 1] - cur[x + 1]); + rPercent = abs(cur[a + 2] - cur[x + 2]); + + all = (bPercent + gPercent + rPercent)/3; + + if(all < threshold) + { + cur[x] = cur[a]; + cur[x+1] = cur[a+1]; + cur[x+2] = cur[a+2]; + } + else + break; + } + break; + } + } + + } + } + } +} + +/* Fills the black holes in the Mat vertically + * from bottom to top + * + * @param the Mat to be processed, the comparison threshold + * @return - + * + */ +void upVerticalFill2(Mat& src, float threshold, bool scale) +{ + uchar *cur; + int channels = src.channels(); + int cols = src.cols; + int rows = src.rows; + int size = cols*rows*channels; + int left; + int right; + int opposite; + float all = 0.0; + float bPercent = 0.0; + float gPercent = 0.0; + float rPercent = 0.0; + + for(int y = 0; y < 1; y++) + { + cur = src.ptr(y); + for(int x = size; x > cols*channels; x = x - channels) + { + opposite = 0; + if(cur[x] != 0 && ((cur[x - cols*channels] == 0 && channels == 1) || (channels > 1 && (cur[x+1] != 0 | cur[x+2] != 0) ))) + { + + int start = ((x - 2*cols*channels) > 0)?(x - 2*cols*channels):0; + + for(int a = start; a > 0 ; a = a - cols*channels) + { + if(cur[a] != 0) + { + if(channels == 1) + { + all = abs( (float(cur[a])/255) - (float(cur[x])/255) ); + if(all < threshold) + { + opposite = a; + } + } + break; + } + } + if(opposite == 0) + continue; + start = x - cols*channels; + for(int k = start; k > opposite; k = k - cols*channels) + { + left = 0; + right = 0; + for(int a = k; a < size ; a = a + channels) + { + //check not to change line + if((k%(cols*channels)) > (a%(cols*channels))) + break; + if(cur[a] != 0) + { + if(channels == 1) + { + all = abs( (float(cur[a])/255) - (float(cur[x])/255) ); + if(all < threshold) + { + right = a; + } + } + else if(cur[a + 1] == 0 && cur[a + 2] == 0) + { + bPercent = abs( (float(cur[a])/255) - (float(cur[x])/255) ); + gPercent = abs( (float(cur[a + 1])/255) - (float(cur[x + 1])/255) ); + rPercent = abs( (float(cur[a + 2])/255) - (float(cur[x + 2])/255) ); + + all = (bPercent + gPercent + rPercent)/3; + + if(all < threshold) + { + for(int i = start; i < a; i = i + channels) + { + cur[i] = cur[x]; + cur[i+1] = cur[x+1]; + cur[i+2] = cur[x+2]; + + } + + + } + } + break; + } + } + for(int a = k; a > 0 ; a = a - channels) + { + //check not to change line + if((k%(cols*channels)) < (a%(cols*channels))) + break; + if(cur[a] != 0) + { + if(channels == 1) + { + all = abs( (float(cur[a])/255) - (float(cur[x])/255) ); + if(all < threshold) + { + left = a; + } + } + else if(cur[a + 1] == 0 && cur[a + 2] == 0) + { + bPercent = abs( (float(cur[a])/255) - (float(cur[x])/255) ); + gPercent = abs( (float(cur[a + 1])/255) - (float(cur[x + 1])/255) ); + rPercent = abs( (float(cur[a + 2])/255) - (float(cur[x + 2])/255) ); + + all = (bPercent + gPercent + rPercent)/3; + + if(all < threshold) + { + for(int i = start; i > a; i = i - channels) + { + cur[i] = cur[x]; + cur[i+1] = cur[x+1]; + cur[i+2] = cur[x+2]; + } + } + } + break; + } + } + if(left == 0 || right == 0) + continue; + if(abs(left - right) > 10 ) + continue; + all = abs( (float(cur[left])/255) - (float(cur[right])/255) ); + if(all > threshold) + { + continue; + } + all = float(cur[left]) - float(cur[right]) ; + all = (all/abs(left - right)); + int ratio = 1; + for(int a = left + channels; a < right; a = a + channels) + { + if(scale) + { + cur[a] = cur[left] - ratio*all; + ratio++; + + } + else + { + cur[a] = cur[x]; + } + } + + } + } + } + } +} diff --git a/vision/src/vision.cpp b/vision/src/vision.cpp index 02e94a4..e92bb71 100644 --- a/vision/src/vision.cpp +++ b/vision/src/vision.cpp @@ -1,21 +1,29 @@ #include -/* Detects non-black areas in the image and populates a list of OpenCV Rects +/* Detects non-black rectangle areas in a black image. This + * to produce ROIS(Regions of interest) for further processing. + * * - * PARAMETERS: -the vector that will be populated - * -screen width + * PARAMETERS: + * - src : the Mat object that holds the image + * - colour_areas : the rectangles produced + * - range : the starting dimension of each rectangle + * - detect_people: the starting dimension of each rectangle * * RETURN -- */ -void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range) +void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range, bool detect_people) { - float detectionFactor = 0.1; - float mergeFactor = 0.1; - bool flag = false; - int channels = src.channels(); - int cols = src.cols; - int rows = src.rows; - int size = cols*rows*channels; + bool flag = false; + int cols = src.cols; + int rows = src.rows; + int channels = src.channels(); + int size = cols*rows*channels; + float detection_factor = 0.1; //threshold for the 1st fusing phase + float merge_factor = 0.1; //threshold for the 2nd fusing phase + + //Starting from the 1st non-zero pixel it starts forming rectangles (range x range) + //and fuses them if their intersection is above a certain threshold. for(int y = 0; y < 1; y++) { const uchar *dif = src.ptr(y); @@ -53,7 +61,7 @@ void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range) if(removal.area() < rect.area()) { - if(threshold > detectionFactor*removal.area()) + if(threshold > detection_factor*removal.area()) { colour_areas[k] = all; flag = true; @@ -61,7 +69,7 @@ void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range) } else { - if(threshold > detectionFactor*rect.area()) + if(threshold > detection_factor*rect.area()) { colour_areas[k] = all; flag = true; @@ -75,6 +83,8 @@ void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range) else flag = false; + //In this phase we loop through all the produced rectangles and again try to merge those whose + //intersection is above a certain threshold int end = colour_areas.size(); for(int a = 0; a < end; a++) { @@ -94,7 +104,7 @@ void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range) if(removal.area() < rect.area()) { - if(threshold > mergeFactor*removal.area()) + if(threshold > merge_factor*removal.area()) { colour_areas[a] = all; colour_areas[b] = colour_areas.back(); @@ -105,7 +115,7 @@ void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range) } else { - if(threshold > mergeFactor*rect.area()) + if(threshold > merge_factor*rect.area()) { colour_areas[a] = all; colour_areas[b] = colour_areas.back(); @@ -130,6 +140,7 @@ void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range) } int end = colour_areas.size(); + //Filter out erroneous areas (dimensions < 0) that sometimes occur for(int k = 0; k < end; k++) { float width = colour_areas[k].width; @@ -139,7 +150,7 @@ void detectBlobs(Mat& src, vector< Rect_ >& colour_areas, int range) if((x < 0) || (y < 0) || (height < 0) || (width < 0)) { //~ rectangle(src, colour_areas[k], 0, CV_FILLED); - cout<<"done"< >& colour_areas, int range) } end = colour_areas.size(); - for(int k = 0; k < end; k++) - { - float width = colour_areas[k].width; - float height = colour_areas[k].height; - float area = colour_areas[k].area(); - float ratio = width/height; - if((ratio < 0.25) || (ratio > 1.5) || (area < cols*rows*0.02)) - { - //~ rectangle(src, colour_areas[k], 0, CV_FILLED); - colour_areas[k] = colour_areas.back(); - colour_areas.pop_back(); - k--; - end--; - - } - } - - /* - for(int k = 0; k < end; k++) + //Filter out areas whose ratio cannot belong to a human + if(detect_people) { - if(colour_areas[k].width > 250) + for(int k = 0; k < end; k++) { - colour_areas[k].width = colour_areas[k].width/2; - Rect_ rect = colour_areas[k]; - rect.x = rect.x + rect.width; - rect.width = colour_areas[k].width; - colour_areas.push_back(rect); - k--; - end++; - + float width = colour_areas[k].width; + float height = colour_areas[k].height; + float area = colour_areas[k].area(); + float ratio = width/height; + if((ratio < 0.25) || (ratio > 1.5) || (area < cols*rows*0.02)) + { + //~ rectangle(src, colour_areas[k], 0, CV_FILLED); + colour_areas[k] = colour_areas.back(); + colour_areas.pop_back(); + k--; + end--; + + } } - } - */ //~ cout<<"Size: "< >& colour_areas, int range) * is redetected and decreases otherwise. The threshold that is used to compare * the detected boxes with the stored ones. * - * PARAMETERS: -current image rectangles - * -the collection to be populated - * -the initial rank of a new box, - * -rectangle comparison threshold + * + * PARAMETERS: + * - cur_boxes : current image rectangles + * - collection : the collection to be populated + * - rank : the initial rank of a new box, + * - threshold :rectangle comparison threshold * * RETURN -- */ @@ -268,74 +267,7 @@ void track(vector< Rect_ >& cur_boxes, People& collection, int rank, float } } -/*Converts a grayscale Mat to a depth Mat by using the maximum depth value - * - * PARAMETERS: - * -Mat depth - * -Mat with the graysclae result - * -float minimum depth - * -float maximum depth - * - * RETURN: -- - */ -void grayToDepth(Mat& src, Mat& dst, float max_depth) -{ - Mat temp_img(src.rows, src.cols, CV_32FC1); - int cols = src.cols; - int rows = src.rows; - if(src.isContinuous()) - { - cols *= rows; - rows = 1; - } - for(int i = 0; i < rows; i++) - { - uchar* cur = src.ptr(i); - float* Ii = temp_img.ptr(i); - for(int j = 0; j < cols; j++) - { - Ii[j] = (max_depth*(float(cur[j])/(255.0))); - } - } - dst = temp_img.clone(); - -} - -/*Converts a depth Mat to a grayscale one by using the min and maximum depth values - * - * PARAMETERS: - * -Mat depth - * -Mat with the graysclae result - * -float minimum depth - * -float maximum depth - * - * RETURN: -- - */ -void depthToGray(Mat& src, Mat& dst, float min_depth, float max_depth) -{ - - Mat temp_img(src.rows, src.cols, CV_8UC1); - int cols = src.cols; - int rows = src.rows; - if(src.isContinuous()) - { - cols *= rows; - rows = 1; - } - for(int i = 0; i < rows; i++) - { - float* cur = src.ptr(i); - uchar* Ii = temp_img.ptr(i); - for(int j = 0; j < cols; j++) - { - Ii[j] = (255*((cur[j] - min_depth)/(max_depth - min_depth))); - } - } - dst = temp_img.clone(); - -} - -/* Calculates and stores the real world coordinates (x, y, z) of a face +/* Calculates and stores the real world coordinates (x, y, z) of a rectangle * in respect to the center of the camera. * * PARAMETERS: @@ -418,334 +350,6 @@ void calculatePosition(Rect& rect, Position& pos, int width, int height, int Hfi } -/* Calculates the depth of the closest object in the specified Mat by using clustering - * - * PARAMETERS: - * -Mat - * -number of values to calculate - * - * RETURN: - * -Double holding the min cluster median value - * - */ -double calculateDepth(Mat& src, Rect_ personRect) -{ - - int clusters = 2; - int cols = src.cols; - int rows = src.rows; - int channels = src.channels(); - int size = cols*rows*channels; - double median = 0.0; - double saveMin = 0.0; - double saveCluster = 0.0; - double saveCenter = 0.0; - double depthCombined = 0.0; - vector vec; - vector cluster_vec; - - if(cols > 0 && rows > 0) - { - - if(src.isContinuous()) - { - rows = 1; - cols = size; - } - - cols = src.cols*0.7; - rows = src.rows*0.4; - - for(int i = 0; i < rows; i++) - { - const float* cur = src.ptr(i); - for(int j = 0; j < cols; j++) - { - cluster_vec.push_back(cur[j]); - } - - } - - // clustering - kmeansreport rep = clusterize(cluster_vec, clusters); - - // cluster item count - int counter[clusters]; - for(int i = 0; i < clusters; i++) - { - counter[i] = 0; - } - for(int i = 0; i < rep.cidx.length(); i++) - { - if(rep.cidx[i] > 0 && rep.cidx[i] < clusters) - counter[rep.cidx[i]]++; - } - - //check which centroid has the smallest value - int min_centroid = INT_MAX; - int index [clusters + 1]; - for(int i = 0; i < clusters + 1; i++) - { - index[i] = -1; - } - - if(rep.c.rows() > 0) - { - for(int i = 0; i < clusters; i++) - { - if((min_centroid > rep.c[i][0]) && (rep.c[i][0] > 0)) - { - min_centroid = rep.c[i][0]; - index[0] = i; - } - } - index[index[0] + 1] = INT_MAX; - - //~ cout<(i); - for(int j = 0; j < cols; j++) - { - if(index[0] == rep.cidx[i*cols + j]) - { - cluster_vec.push_back(cur[j]); - } - } - } - - //median - nth_element(cluster_vec.begin(), cluster_vec.begin() + cluster_vec.size()/2, cluster_vec.end()); - median = cluster_vec[cluster_vec.size()/2]; - for(int i = 1; i < clusters + 1; i++) - { - if(index[i] == -1) - { - index[0] = i - 1; - index[i] = INT_MAX; - break; - } - } - } - - //~ printf("%s %2.3f\n","Depth: " ,median); - - /* - Mat src_gray; - depthToGray(src, src_gray, 0, max_depth); - for(int i = 0; i < rows; i++) - { - uchar* cur = src_gray.ptr(i); - for(int j = 0; j < cols; j++) - { - if(rep.cidx[i*cols + j] == index[0]) - { - cur[j] = 0; - } - else - { - cur[j] = 255; - } - } - } - - Mat temp_img(height, depth_width, CV_8UC1); - temp_img = Scalar(0); - - src.copyTo(temp_img(Rect(personRect.x, personRect.y, cols, rows))); - imshow("Clustered", temp_img); - moveWindow("Clustered", 645, 0); - */ - - } - - } - return median; - - - /* - // Preprocessing step to discard null or unwanted depth values - // and convert Mat to vector - for(int i = 0; i < rows; i++) - { - float* cur = src.ptr(i); - for(int j = 0; j < cols; j++) - { - vec.push_back(cur[j]); - } - - } - // average of minimum vector elements - saveMin = minDepth(vec, 20); - - // find the depth of the mat center area - saveCenter = centerDepth(src, 10); - - - - - //~ int id = -1; - //~ double result = FLT_MAX; - //~ - //~ for(int i = 0; i < rep.c.rows() - 1; i++) - //~ { - //~ double temp = std::min(result, rep.c[i + 1][0]); - //~ if(temp > 0) - //~ { - //~ id = i; - //~ result = temp; - //~ } - //~ } - //~ saveCluster = result; - - //combine the results of the 2 closest - depthCombined = combineDepth(saveMin, saveCenter, median, 0, max_depth); - - - //~ printf("%s %2.3f\n","Depth combined: " ,depthCombined); - return depthCombined; - */ - -} - -/* Finds an average of the minimum - * values of a given vector - * - * PARAMETERS: - * -vector with the values - * -number of values to calculate - * - * RETURN: - * -Double holding the average value - * - */ -double minDepth(vector vec, int number) -{ - double result = 0; - double min = 0; - int done = 0; - float threshold = number; - partial_sort (vec.begin(), vec.begin() + threshold, vec.end()); - for(int i = 0; i < threshold; i++) - { - result += vec.at(i); - } - result = result/threshold; - cout<<"Save Min: "<(src.rows/2 - number/2 + i, src.cols/2 - number/2 + j); - if(std::isnan(temp) || temp == FLT_MAX) - continue; - result += temp; - counter++; - } - } - - cout<<"Save Center: "< max_depth) - //~ { - //~ return FLT_MAX; - //~ } - return result/counter; -} - -/* Calculates an average of the 2 closest values - * - * PARAMETERS: - * -Double the min depth approximation - * -Double the center depth approximation - * -Double the cluster depth approximation - * - * - * RETURN: - * -Double holding the average of the 2 closest values - */ -double combineDepth(double saveMin, double saveCenter, double saveCluster, double min_depth, double max_depth) -{ - double result; - double minClusterDif; - double minCenterDif; - double clusterCenterDif; - - - - - if((saveMin == FLT_MAX || saveMin == 0) && (saveCluster == FLT_MAX || saveCluster == 0)) - minClusterDif = FLT_MAX; - else - minClusterDif = abs(saveMin - saveCluster); - - if((saveMin == FLT_MAX || saveMin == 0) && (saveCenter == FLT_MAX || saveCenter == 0)) - minCenterDif = FLT_MAX; - else - minCenterDif = abs(saveMin - saveCenter); - - if((saveCluster == FLT_MAX || saveCluster == 0) && (saveCenter == FLT_MAX || saveCenter == 0)) - clusterCenterDif = FLT_MAX; - else - clusterCenterDif = abs(saveCluster - saveCenter); - - - if(minClusterDif > max_depth/10) - minClusterDif = FLT_MAX; - if(minCenterDif > max_depth/10) - minCenterDif = FLT_MAX; - if(clusterCenterDif > max_depth/10) - clusterCenterDif = FLT_MAX; - - if(minClusterDif < minCenterDif) - { - if(minClusterDif < clusterCenterDif) - result = (saveMin + saveCluster)/2; - else - result = (saveCluster + saveCenter)/2; - } - else if(minCenterDif < clusterCenterDif) - result = (saveMin + saveCenter )/2; - else if(clusterCenterDif < minClusterDif) - result = (saveCenter + saveCluster)/2; - else - { - result = max(saveMin, saveCenter); - result = max(result, saveCluster); - } - - - return result; -} - /* Estimates the foreground by combining static images, works for * images the contain edge information * @@ -873,485 +477,6 @@ void frameDif(Mat& src1, Mat& src2, Mat& dst, float threshold) } } -/*Region growing algorithm that fills black holes in the depth image, uses - * rectangular areas - * - * PARAMETERS: - * -Mat to be corrected - * -float threshold of correction - * -int range of each correctin area - * - * RETURN: -- - */ -void rectFill(Mat& src, float threshold, int range) -{ - uchar *cur, *temp,*vFill; - int channels = src.channels(); - int cols = src.cols; - int rows = src.rows; - int size = cols*rows*channels; - int count = 0; - float all = 0.0; - float bPercent = 0.0; - float gPercent = 0.0; - float rPercent = 0.0; - bool has_zero = false; - bool flag = false; - - for(int y = 0; y < 1; y++) - { - cur = src.ptr(y); - for(int x = channels*range + cols*range; x < size - (channels*range + cols*range); x = x + channels) - { - if ((cur[x] != 0 && channels == 1) || (channels > 1 && (cur[x+1] != 0 || cur[x+2] != 0) )) - { - int top = x - range*cols*channels; - int topLeft = top - range*channels; - int topRight = top + range*cols*channels; - int bottom = x + range*cols*channels; - int bottomLeft = bottom - range*cols*channels; - int bottomRight = bottom + range*cols*channels; - - if(topLeft%(cols*channels) > top%(cols*channels)) - continue; - if(topRight%(cols*channels) < top%(cols*channels)) - continue; - - has_zero = false; - flag = false; - count = 0; - for(int a = topLeft; a < bottomLeft; a = a + cols*channels) - { - for(int b = a; b < a + 2*range*channels ; b += channels) - { - if (cur[b] == 0) - { - has_zero = true; - count++; - } - else - { - if(channels == 1) - { - all = abs( (float(cur[b])/255) - (float(cur[x])/255) ); - if(all >= threshold) - flag = true; - } - } - - } - } - int countThresh = range; - if(!flag && has_zero && (count <= countThresh)) - { - for(int a = topLeft; a < bottomLeft; a = a + cols*channels) - { - for(int b = a; b < a + 2*range*channels ; b += channels) - { - if (cur[b] == 0) - { - cur[b] = cur[x]; - } - } - } - } - //~ x = x - range*channels + channels; - } - } - } -} - -/* Fills the black holes in the Mat horizontally - * - * PARAMETERS: - * -the Mat to be processed - * -the comparison threshold - * - * RETURN: -- - * - */ -void rightHorizontalFill(Mat& cur_Mat, float threshold, bool scale) -{ - uchar *cur; - int channels = cur_Mat.channels(); - int cols = cur_Mat.cols; - int rows = cur_Mat.rows; - int size = cols*rows*channels; - float all = 0.0, bPercent = 0.0, gPercent = 0.0, rPercent = 0.0; - - for(int y = 0; y < 1; y++) - { - cur = cur_Mat.ptr(y); - for(int x = 0; x < size; x = x + channels) - { - /*If it is the end of the current line, continue*/ - if(x > 0 && (x%(cols*channels) == 0 || x%(cols*channels) == (cols - 1))) - continue; - if(cur[x] != 0 && ((cur[x + channels] == 0 && channels == 1) || (channels > 1 && (cur[x+1] != 0 | cur[x+2] != 0) ))) - { - int start = x + 2*channels; - for(int a = start; a < size; a = a + channels) - { - //check not to change line - if((x%(cols*channels)) > (a%(cols*channels))) - break; - if(cur[a] != 0) - { - if(channels == 1) - { - all = abs( (float(cur[a])/255) - (float(cur[x])/255) ); - if(all < threshold) - { - if(scale) - { - int rowA = a%(cols*channels); - int rowX = x%(cols*channels); - all = (all/abs(rowA - rowX))*255; - int ratio = 1; - for(int i = x + channels; i < a; i = i + channels) - { - cur[i] = cur[x] + ratio*all; - ratio++; - } - } - else - { - for(int i = x + channels; i < a; i = i + channels) - cur[i] = (cur[x] + cur[a])/2; - } - } - } - else if(cur[a + 1] == 0 && cur[a + 2] == 0) - { - - - bPercent = abs( (double(cur[a])/255) - (double(cur[x])/255) ); - gPercent = abs( (double(cur[a + 1])/255) - (double(cur[x + 1])/255) ); - rPercent = abs( (double(cur[a + 2])/255) - (double(cur[x + 2])/255) ); - - all = bPercent + gPercent + rPercent; - - if(all < threshold){ - cur[a] = cur[x]; - cur[a+1] = cur[x+1]; - cur[a+2] = cur[x+2]; - } - else - break; - } - break; - } - } - } - } - } -} - -/* Fills the black holes in the Mat vertically - * from bottom to top - * - * @param the Mat to be processed, the comparison threshold - * @return - - * - */ -void upVerticalFill(Mat& src, float threshold, bool flag) -{ - uchar *cur; - int channels = src.channels(); - int cols = src.cols; - int rows = src.rows; - int size = cols*rows*channels; - float all = 0.0; - float bPercent = 0.0; - float gPercent = 0.0; - float rPercent = 0.0; - - threshold *= 255; - float threshold2 = 0.01*255; - for(int y = 0; y < 1; y++) - { - cur = src.ptr(y); - for(int x = size; x > cols*channels; x = x - channels) - { - - if(int(cur[x]) != 0 && ((int(cur[x - cols*channels]) == 0 && channels == 1) || (channels > 1 && (cur[x+1] != 0 | cur[x+2] != 0) ))) - { - - int start = ((x - 2*cols*channels) > 0)?(x - 2*cols*channels):0; - //~ int end = ((start + cols*verRange) < size)?(start + cols*verRange):size; - - for(int a = start; a > 0 ; a = a - cols*channels) - { - if((x - a)/(cols*channels) > rows/10) - { - break; - } - if(int(cur[a]) != 0) - { - if(channels == 1) - { - all = abs(int(cur[a]) - int(cur[x])); - if(all < threshold) - { - int ratio = 1; - int rowA = floor(a/(cols*channels)); - int rowX = floor(x/(cols*channels)); - int color = int(cur[x]) - int(cur[a]); - color /= abs(rowA - rowX); - - for(int i = x - cols*channels; i > a; i = i - cols*channels) - { - cur[i] = int(cur[x]) - ratio*color; - ratio++; - } - } - else - { - for(int i = x - cols*channels; i > a; i = i - cols*channels) - { - int left = 0; - int right = 0; - for(int j = i; j < size ; j = j + channels) - { - //check not to change line - if((i%(cols*channels)) > (j%(cols*channels))) - break; - if(cur[j] != 0) - { - if(channels == 1) - { - right = j; - } - break; - } - } - for(int j = i; j > 0 ; j = j - channels) - { - //check not to change line - if((i%(cols*channels)) < (j%(cols*channels))) - break; - if(cur[j] != 0) - { - if(channels == 1) - { - left = j; - } - break; - } - } - if(!flag) - { - if((abs(int(cur[x]) - int(cur[left])) < threshold)) - { - cur[i] = int(cur[left]) - (int(cur[left]) - int(cur[x]))/abs(left - x); - } - else if((abs(int(cur[x]) - int(cur[right])) < threshold)) - { - cur[i] = int(cur[right]) - (int(cur[right]) - int(cur[x]))/abs(right - x); - } - } - else - { - //~ if(abs(int(cur[left]) - int(cur[right])) < threshold) - //~ { - cur[i] = int(cur[x]); - //~ } - } - //~ else - //~ { - //~ cur[i] = int(cur[a]); - //~ } - } - } - } - else if(cur[a + 1] == 0 && cur[a + 2] == 0) - { - bPercent = abs(cur[a] - cur[x]); - gPercent = abs(cur[a + 1] - cur[x + 1]); - rPercent = abs(cur[a + 2] - cur[x + 2]); - - all = (bPercent + gPercent + rPercent)/3; - - if(all < threshold) - { - cur[x] = cur[a]; - cur[x+1] = cur[a+1]; - cur[x+2] = cur[a+2]; - } - else - break; - } - break; - } - } - - } - } - } -} - -/* Fills the black holes in the Mat vertically - * from bottom to top - * - * @param the Mat to be processed, the comparison threshold - * @return - - * - */ -void upVerticalFill2(Mat& src, float threshold, bool scale) -{ - uchar *cur; - int channels = src.channels(); - int cols = src.cols; - int rows = src.rows; - int size = cols*rows*channels; - int left; - int right; - int opposite; - float all = 0.0; - float bPercent = 0.0; - float gPercent = 0.0; - float rPercent = 0.0; - - for(int y = 0; y < 1; y++) - { - cur = src.ptr(y); - for(int x = size; x > cols*channels; x = x - channels) - { - opposite = 0; - if(cur[x] != 0 && ((cur[x - cols*channels] == 0 && channels == 1) || (channels > 1 && (cur[x+1] != 0 | cur[x+2] != 0) ))) - { - - int start = ((x - 2*cols*channels) > 0)?(x - 2*cols*channels):0; - - for(int a = start; a > 0 ; a = a - cols*channels) - { - if(cur[a] != 0) - { - if(channels == 1) - { - all = abs( (float(cur[a])/255) - (float(cur[x])/255) ); - if(all < threshold) - { - opposite = a; - } - } - break; - } - } - if(opposite == 0) - continue; - start = x - cols*channels; - for(int k = start; k > opposite; k = k - cols*channels) - { - left = 0; - right = 0; - for(int a = k; a < size ; a = a + channels) - { - //check not to change line - if((k%(cols*channels)) > (a%(cols*channels))) - break; - if(cur[a] != 0) - { - if(channels == 1) - { - all = abs( (float(cur[a])/255) - (float(cur[x])/255) ); - if(all < threshold) - { - right = a; - } - } - else if(cur[a + 1] == 0 && cur[a + 2] == 0) - { - bPercent = abs( (float(cur[a])/255) - (float(cur[x])/255) ); - gPercent = abs( (float(cur[a + 1])/255) - (float(cur[x + 1])/255) ); - rPercent = abs( (float(cur[a + 2])/255) - (float(cur[x + 2])/255) ); - - all = (bPercent + gPercent + rPercent)/3; - - if(all < threshold) - { - for(int i = start; i < a; i = i + channels) - { - cur[i] = cur[x]; - cur[i+1] = cur[x+1]; - cur[i+2] = cur[x+2]; - - } - - - } - } - break; - } - } - for(int a = k; a > 0 ; a = a - channels) - { - //check not to change line - if((k%(cols*channels)) < (a%(cols*channels))) - break; - if(cur[a] != 0) - { - if(channels == 1) - { - all = abs( (float(cur[a])/255) - (float(cur[x])/255) ); - if(all < threshold) - { - left = a; - } - } - else if(cur[a + 1] == 0 && cur[a + 2] == 0) - { - bPercent = abs( (float(cur[a])/255) - (float(cur[x])/255) ); - gPercent = abs( (float(cur[a + 1])/255) - (float(cur[x + 1])/255) ); - rPercent = abs( (float(cur[a + 2])/255) - (float(cur[x + 2])/255) ); - - all = (bPercent + gPercent + rPercent)/3; - - if(all < threshold) - { - for(int i = start; i > a; i = i - channels) - { - cur[i] = cur[x]; - cur[i+1] = cur[x+1]; - cur[i+2] = cur[x+2]; - } - } - } - break; - } - } - if(left == 0 || right == 0) - continue; - if(abs(left - right) > 10 ) - continue; - all = abs( (float(cur[left])/255) - (float(cur[right])/255) ); - if(all > threshold) - { - continue; - } - all = float(cur[left]) - float(cur[right]) ; - all = (all/abs(left - right)); - int ratio = 1; - for(int a = left + channels; a < right; a = a + channels) - { - if(scale) - { - cur[a] = cur[left] - ratio*all; - ratio++; - - } - else - { - cur[a] = cur[x]; - } - } - - } - } - } - } -} - /* Image gamma correction * * @param the Mat to be processed @@ -1374,41 +499,4 @@ void gammaCorrection(Mat& src) LUT( here, lut_matrix, here ); } -/* Clusterizes a given vector - * - * PARAMETERS: - * -Vec with the values - * -Int with the number of clusters - * - * RETURN: - * -Double holding the minimum cluster value - * - */ -kmeansreport clusterize(const vector& vec, int clusters) -{ - clusterizerstate s; - kmeansreport rep; - - real_2d_array matrix; - matrix.setlength(vec.size(), 1); - - for (int i = 0; i < vec.size(); i++) - { - matrix(i, 0) = vec.at(i); - } - - try - { - clusterizercreate(s); - clusterizersetpoints(s, matrix, 2); - clusterizersetkmeanslimits(s, 5, 0); - clusterizerrunkmeans(s, clusters, rep); - } - catch(exception& e) - { - printf("%s %s", "Clusterize failed", e.what()); - } - return rep; - -}