LBP特征提取
重点有以下几个:
1.普通LBP所采用的邻域是一个3*3方格,可以用一个圆形区域来代替,但计算圆形区域上的点的像素值比较麻烦,需要用到双线性插值。
2.得到一个LBP值(一个8位值)后,考虑到旋转不变性,可以把这个值循环左移8次,求出8次中最小的值,并最终输出这个最小值。
3.考虑LBP的uniform pattern,即一个数用二进制表示后,若左移一位并亦或,各个位置上(除去最后一位)的1不超过2个,则可将其归为uniform pattern。否则归为另一类。考虑旋转不变性后类别总共有9类。建立类别的直方图统计。
4.实际编程时可以将图片分成8*8块小区域,然后分别建立每一小块的直方图,最后把64个直方图连起来作为这张图片的特征。
#include<iostream> #include<cv.h> #include<highgui.h> #include<map> using namespace std; using namespace cv; uchar calcLBP(Mat_<double>& image,int i, int j, int radius,int neighbor) { double r; uchar v = 0; for (int n = 0; n < neighbor; n++) { double x = -radius*sin(2.0*CV_PI*n / neighbor); double y = radius*cos(2.0*CV_PI*n / neighbor); int fx = static_cast<int>(floor(x));//向下取整 int fy = static_cast<int>(floor(y)); int cx = static_cast<int>(ceil(x));//向上取整 int cy = static_cast<int>(ceil(y)); double ty = y - fy; double tx = x - fx; double w1 = (1 - tx)*(1 - ty); double w4 = tx*ty; double w2 = tx*(1 - ty); double w3 = (1 - tx)*ty; r = image(i + fx, j + fy)*w1 + image(i + fx, j + cy)*w2 + image(i + cx, j + fy)*w3 + image(i + cx, j + cy)*w4; v += (r >= image(i, j)) << n; } return v; } uchar shift_min(uchar v) { uchar vmin = v; for (int k = 0; k < 8; k++) { uchar left = v << 1; uchar right = (v >> (8 - 1)); v = left | right; vmin = min(v, vmin); } return vmin; } int calcHop(uchar v) { int num = 0; uchar bits[8]; for (int k = 0; k < 8; k++) { int t = v >> (8 - k - 1); bits[k] = t & 1; } for (int k = 0; k < 7; k++) { if (bits[k] ^ bits[k + 1] == 1) num++; } return num; } int main() { Mat_<double> image = imread("E:\\COFW_Dataset\\trainingImages\\1.jpg", 0); int neighbors = 8; int radius = 16; int border = 20; int right = radius - image.cols%radius + border; int bottom = radius - image.rows%radius + border; copyMakeBorder(image, image, border, bottom, border, right, BORDER_REFLECT); int hop; map<int, int> imap; int num = 0; for (int i = 0; i < 256; i++) { int vmin = (int)shift_min((uchar)i); hop = calcHop(vmin); if (hop <= 2 && imap.find(vmin) == imap.end()) { imap.insert(make_pair(vmin, num++)); } } //vector<vector<int> > histogram(num, 0); Mat_<int> histogram(64, num); histogram.setTo(0); Mat_<uchar> result(image.rows - 2 * border, image.cols - 2 * border); int chuckwidth = (image.cols - 2 * border) / 8; int chuckheight = (image.rows - 2 * border) / 8; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { Mat_<double> tmp = image(Rect(border + chuckwidth*j, border + chuckheight*i, chuckwidth, chuckheight)); copyMakeBorder(tmp, tmp, border, border, border, border, BORDER_REFLECT); int order = i * 8 + j; for (int k1 = 0; k1 < chuckheight; k1++) { for (int k2 = 0; k2 < chuckwidth; k2++) { uchar val = shift_min(calcLBP(tmp, k1, k2, radius, neighbors)); if (imap.find(val) != imap.end()) { histogram(order, imap[val])++; } else { histogram(order, 8)++; } } } /*for (int i = border; i < image.rows - border; i++) { for (int j = border; j < image.cols - border; j++) { result(i - 20, j - 20) = shift_min(calcLBP(image, i, j, radius, neighbors)); if (imap.find(result(i - 20, j - 20)) != imap.end()) { histogram[imap[result(i - 20, j - 20)]]++; } else { histogram[8]++; } } }*/ } } histogram.reshape(0, 64 * num); imshow("1", result); waitKey(0); return 0; }
浙公网安备 33010602011771号