Python+OpenCV:图像二进制鲁棒独立基本特征(BRIEF, Binary Robust Independent Elementary Features)
理论
We know SIFT uses 128-dim vector for descriptors. Since it is using floating point numbers, it takes basically 512 bytes. Similarly SURF also takes minimum of 256 bytes (for 64-dim).
Creating such a vector for thousands of features takes a lot of memory which are not feasible for resource-constraint applications especially for embedded systems. Larger the memory, longer the time it takes for matching.
But all these dimensions may not be needed for actual matching. We can compress it using several methods like PCA, LDA etc.
Even other methods like hashing using LSH (Locality Sensitive Hashing) is used to convert these SIFT descriptors in floating point numbers to binary strings.
These binary strings are used to match features using Hamming distance.
This provides better speed-up because finding hamming distance is just applying XOR and bit count, which are very fast in modern CPUs with SSE instructions.
But here, we need to find the descriptors first, then only we can apply hashing, which doesn't solve our initial problem on memory.
BRIEF comes into picture at this moment. It provides a shortcut to find the binary strings directly without finding descriptors.
It takes smoothened image patch and selects a set of nd (x,y) location pairs in an unique way (explained in paper). Then some pixel intensity comparisons are done on these location pairs.
For eg, let first location pairs be p and q. If I(p)<I(q), then its result is 1, else it is 0. This is applied for all the nd location pairs to get a nd-dimensional bitstring.
This nd can be 128, 256 or 512. OpenCV supports all of these, but by default, it would be 256 (OpenCV represents it in bytes. So the values will be 16, 32 and 64).
So once you get this, you can use Hamming Distance to match these descriptors.
One important point is that BRIEF is a feature descriptor, it doesn't provide any method to find the features. So you will have to use any other feature detectors like SIFT, SURF etc.
The paper recommends to use CenSurE which is a fast detector and BRIEF works even slightly better for CenSurE points than for SURF points.
In short, BRIEF is a faster method feature descriptor calculation and matching. It also provides high recognition rate unless there is large in-plane rotation.
BRIEF in OpenCV
####################################################################################################
# 图像二进制鲁棒独立基本特征(BRIEF, Binary Robust Independent Elementary Features)
def lmc_cv_image_binary_robust_detection():
"""
函数功能: 图像二进制鲁棒独立基本特征(BRIEF, Binary Robust Independent Elementary Features)。
"""
stacking_images = []
image_file_name = ['D:/99-Research/Python/Image/Butterfly01.jpg',
'D:/99-Research/Python/Image/Butterfly02.jpg',
'D:/99-Research/Python/Image/Butterfly03.jpg',
'D:/99-Research/Python/Image/Butterfly04.jpg']
for i in range(len(image_file_name)):
# 读取图像
image = lmc_cv.imread(image_file_name[i])
image = lmc_cv.cvtColor(image, lmc_cv.COLOR_BGR2RGB)
gray_image = lmc_cv.cvtColor(image, lmc_cv.COLOR_BGR2GRAY)
# Initiate FAST detector
star = lmc_cv.xfeatures2d.StarDetector_create()
# Initiate BRIEF extractor
brief = lmc_cv.xfeatures2d.BriefDescriptorExtractor_create()
# find the keypoints with STAR
keypoints = star.detect(gray_image, None)
# compute the descriptors with BRIEF
keypoints, descriptors = brief.compute(gray_image, keypoints)
print("描述子个数: {}".format(brief.descriptorSize()))
print("描述子形状:{}".format(descriptors.shape))
result_image = lmc_cv.drawKeypoints(gray_image, keypoints, None, color=(255, 0, 0),
flags=lmc_cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# stacking images side-by-side
stacking_image = np.hstack((image, result_image))
stacking_images.append(stacking_image)
# 显示图像
for i in range(len(stacking_images)):
pyplot.figure('Binary Robust Independent Elementary Features %d' % (i + 1))
pyplot.subplot(1, 1, 1)
pyplot.imshow(stacking_images[i], 'gray')
pyplot.title('Binary Robust Independent Elementary Features')
pyplot.xticks([])
pyplot.yticks([])
pyplot.show()
# 根据用户输入保存图像
if ord("q") == (lmc_cv.waitKey(0) & 0xFF):
# 销毁窗口
pyplot.close('all')
return