00001
00003 #include <cv.h>
00004
00005 #include <vector>
00006 using namespace std;
00007
00008
00009
00010 void ExtractKptArea(const IplImage* img, IplImage* result)
00011 {
00012 cvSmooth(img, result, CV_GAUSSIAN, 3);
00013 cvAdaptiveThreshold(result, result, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 9);
00014 cvDilate(result, result, NULL, 1);
00015 }
00016
00017
00018
00019 int Labeling(const IplImage* area, int *result)
00020 {
00021 int nsort[5];
00022 int x, y, i, flag, countk, label, p;
00023 int labelnumber;
00024 int labelnum = -1;
00025 int map[50000];
00026
00027 map[0] = 0;
00028
00029 int imgw = area->width;
00030 int imgh = area->height;
00031
00032
00033 for(y=1;y<imgh-1;y++){
00034 unsigned char *l = &CV_IMAGE_ELEM(area, unsigned char, y, 0);
00035 for(x=1;x<imgw-1;x++){
00036 result[x+y*imgw] = *l++;
00037 }
00038 }
00039
00040
00041 for(x=0;x<imgw;x++){
00042 result[x] = result[x+(imgh-1)*imgw] = 0;
00043 }
00044 for(y=0;y<imgh;y++){
00045 result[0+y*imgw] = result[(imgw-1)+y*imgw] = 0;
00046 }
00047
00048
00049 label = 0;
00050 for(y=1;y<imgh-1;y++){
00051 for(x=1;x<imgw-1;x++){
00052 map[0] = 0;
00053
00054 if(result[x+y*imgw] == 0){
00055 continue;
00056 }
00057
00058 nsort[0] = 0;
00059 nsort[1] = result[(x-1)+(y-1)*imgw];
00060 nsort[2] = result[x+(y-1)*imgw];
00061 nsort[3] = result[(x+1)+(y-1)*imgw];
00062 nsort[4] = result[(x-1)+y*imgw];
00063
00064 for(flag = 1; flag == 1;){
00065 for(flag = 0, i = 2; i < 5; i++){
00066 if (nsort[i] < nsort[i-1]){
00067 countk = nsort[i];
00068 nsort[i] = nsort[i-1];
00069 nsort[i-1] = countk;
00070 flag = 1;
00071 }
00072 }
00073 }
00074 countk = 0;
00075 for(i = 1; i < 5; i++){
00076 if(nsort[i] == 0){
00077 continue;
00078 }
00079 if(nsort[i] == nsort[i-1]){
00080 continue;
00081 }
00082 countk++;
00083 nsort[countk] = nsort[i];
00084 }
00085
00086 i = countk;
00087 if(i == 0){
00088 label++;
00089 result[x+y*imgw] = label;
00090 map[label] = label;
00091 }
00092 else if(i == 1){
00093 countk = nsort[1];
00094 while(map[countk] != countk){
00095 countk = map[countk];
00096 }
00097 result[x+y*imgw] = countk;
00098 }
00099 else if(i > 1){
00100 countk = nsort[1];
00101 while(map[countk] != countk){
00102 countk = map[countk];
00103 }
00104 result[x+y*imgw] = countk;
00105 for (p = 2; p <= i; p++){
00106 map[nsort[p]] = countk;
00107 }
00108 }
00109 }
00110 }
00111
00112 labelnum=0;
00113 for(labelnumber=1;labelnumber<=label;labelnumber++){
00114 if(map[labelnumber] == labelnumber){
00115 labelnum++;
00116 map[labelnumber] = labelnum;
00117 }
00118 else{
00119 map[labelnumber] = map[map[labelnumber]];
00120 }
00121 }
00122
00123 for(y=1; y<imgh-1; y++){
00124 for(x=1; x<imgw-1; x++){
00125 labelnumber = result[x+y*imgw];
00126 if(labelnumber == 0){
00127 continue;
00128 }
00129 result[x+y*imgw] = map[labelnumber];
00130 }
00131 }
00132
00133 return labelnum+1;
00134 }
00135
00136 struct pt
00137 {
00138 pt():sumx(.0f), sumy(.0f), count(0) {}
00139 float sumx, sumy;
00140 int count;
00141 };
00142
00143
00144
00145
00146
00147 int ExtractKpt(const int *label, const int numlabel, const int imgw, const int imgh, CvMat *kpt)
00148 {
00149 vector<pt> blobs(numlabel+1);
00150
00151 for(int y=1; y<imgh-1; y++){
00152 for(int x=1; x<imgw-1; x++){
00153 if(label[x+y*imgw] == 0){
00154 continue;
00155 }
00156
00157 blobs[label[x+y*imgw]].sumx += static_cast<float>(x);
00158 blobs[label[x+y*imgw]].sumy += static_cast<float>(y);
00159 blobs[label[x+y*imgw]].count++;
00160
00161 }
00162 }
00163
00164 int numkpt = 0;
00165 for(int i=1;i<static_cast<int>(blobs.size());i++){
00166 if(blobs[i].count > 10){
00167 float ptx, pty;
00168 ptx = blobs[i].sumx / static_cast<float>(blobs[i].count);
00169 pty = blobs[i].sumy / static_cast<float>(blobs[i].count);
00170
00171 cvmSet(kpt,numkpt,0,ptx);
00172 cvmSet(kpt,numkpt,1,pty);
00173
00174 numkpt++;
00175 }
00176 }
00177
00178 return numkpt;
00179 }
00180
00181 int detectAdaptiveTresholdKeypoints(const IplImage *img, CvMat *kpt)
00182 {
00183
00184 IplImage* area = cvCreateImage(cvGetSize(img),8,1);
00185
00186
00187 ExtractKptArea(img, area);
00188
00189
00190 int *label = new int[img->width*img->height];
00191 int numlabel = Labeling(area, label);
00192
00193 int numkpt = ExtractKpt(label, numlabel, img->width, img->height, kpt);
00194
00195 cvReleaseImage(&area);
00196 delete [] label;
00197
00198 return numkpt;
00199 }