计算CellBlock的大小

转载,请注明出处!

在Collector.h文件中有如下一行代码:

const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.
我一直不明白这行计算式的原理何在?仔细阅读了相关类之后,心中有所悟。首先阅读Heap::cellBlock函数的实现。如下,
inline CollectorBlock* Heap::cellBlock(const JSCell* cell)
{
    return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell)&BLOCK_MASK);
}
根据这个函数可以得出一个结论,CollectorBlock对象的地址一定是按照BLOCK_SIZE对齐的。CollectorBlock的定义如下,
class CollectorBlock {
public:
    CollectorCell cells[CELLS_PER_BLOCK];
    CollectorBitmap marked;
    Heap* heap;
};

CollectorBlock对象占用的内存大小为:CELL_SIZE * CELLS_PER_BLOCK + CELLS_PER_BLOCK/8 + sizeof(Heap*),这个大小是以字节为单位的。很明显这个大小应该小于BLOCK_SIZE,即CELL_SIZE * CELLS_PER_BLOCK + CELLS_PER_BLOCK/8 + sizeof(Heap*) <= BLOCK_SIZE。如果将这个不等式看做等式,那么可以经过几步转化则可以得到文件中的计算式。转化步骤如下,

(8 * CELL_SIZE * CELLS_PER_BLOCK + CELLS_PER_BLOCK) / 8 = (BLOCK_SIZE - sizeof(Heap*))

(8 * CELL_SIZE + 1) * CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8

CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 / (8 * CELL_SIZE + 1)

CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) * CELL_SIZE

CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE

计算机上除法运算时下取整的。例如:3 / 2 = 1, 100 / 40 = 2等。因此,根据运算式获得的结果不会将BLOCK_SIZE个字节完全占有使用,会遗留一些paddings字节。

好的,首先我们先来编写一个基本的 HOG 特征提取函数: ```python import cv2 import numpy as np def hog(img, cell_size=8, block_size=2, nbins=9): # 计算图像梯度 gx = cv2.Sobel(img, cv2.CV_32F, 1, 0) gy = cv2.Sobel(img, cv2.CV_32F, 0, 1) mag, ang = cv2.cartToPolar(gx, gy) # 归一化角度 ang = np.rad2deg(ang) % 180 # 将图像划分成若干个单元 h, w = img.shape[:2] n_cellsx = w // cell_size n_cellsy = h // cell_size cells = np.zeros((n_cellsy, n_cellsx, nbins)) for i in range(n_cellsy): for j in range(n_cellsx): cell_mag = mag[i * cell_size:(i + 1) * cell_size, j * cell_size:(j + 1) * cell_size] cell_ang = ang[i * cell_size:(i + 1) * cell_size, j * cell_size:(j + 1) * cell_size] hist = np.zeros(nbins) for k in range(cell_mag.shape[0]): for l in range(cell_mag.shape[1]): bin = int(cell_ang[k, l] // (180 / nbins)) hist[bin] += cell_mag[k, l] cells[i, j] = hist # 将若干个单元组成一个块 hog = np.zeros((n_cellsy - block_size + 1, n_cellsx - block_size + 1, block_size * block_size * nbins)) for i in range(hog.shape[0]): for j in range(hog.shape[1]): block = cells[i:i + block_size, j:j + block_size] block = block.ravel() hog[i, j] = block / np.sqrt(np.sum(block ** 2) + 1e-6) return hog.ravel() ``` 其中,我们使用了 OpenCV 库提供的 Sobel 算子来计算梯度,然后将图像划分成若干个单元,对每个单元内的梯度方向进行直方图统计,最后将若干个单元组成一个块,并对块内的特征向量进行 L2 归一化。 接下来,我们可以使用该函数来提取 HOG 特征,并尝试改变一些参数: ```python img = cv2.imread('test.jpg', 0) # 默认参数 hog_default = hog(img) # 改变 cell 大小为 16 hog_cell_16 = hog(img, cell_size=16) # 改变重叠像素大小为 4 hog_overlap_4 = hog(img, cell_size=8, block_size=2, nbins=9) # 改变 bin 大小为 18 hog_bin_18 = hog(img, cell_size=8, block_size=2, nbins=18) ``` 其中,我们将原始图像读入后,分别使用默认参数、改变 cell 大小为 16、改变重叠像素大小为 4、改变 bin 大小为 18 来提取 HOG 特征,并保存到不同的变量中。 我们还可以使用 LBP 来提取图像特征: ```python import skimage.feature # LBP 特征 lbp_feat = skimage.feature.local_binary_pattern(img, 8, 1, method='nri_uniform') lbp_hist, _ = np.histogram(lbp_feat, bins=59, range=(0, 58), density=True) ``` 在该代码中,我们使用 scikit-image 库提供的 local_binary_pattern 函数来提取 LBP 特征,并计算其直方图。 最后,我们可以将不同的特征向量保存到同一个数组中,并进行 SVM 分类器训练: ```python import glob from sklearn.svm import SVC X = [] Y = [] # 加载正样本 for filename in glob.glob('pos/*.jpg'): img = cv2.imread(filename, 0) hog_feat = hog(img) lbp_feat = skimage.feature.local_binary_pattern(img, 8, 1, method='nri_uniform') lbp_hist, _ = np.histogram(lbp_feat, bins=59, range=(0, 58), density=True) feat = np.concatenate((hog_feat, lbp_hist)) X.append(feat) Y.append(1) # 加载负样本 for filename in glob.glob('neg/*.jpg'): img = cv2.imread(filename, 0) hog_feat = hog(img) lbp_feat = skimage.feature.local_binary_pattern(img, 8, 1, method='nri_uniform') lbp_hist, _ = np.histogram(lbp_feat, bins=59, range=(0, 58), density=True) feat = np.concatenate((hog_feat, lbp_hist)) X.append(feat) Y.append(0) # 训练 SVM 分类器 clf = SVC(kernel='linear') clf.fit(X, Y) ``` 在该代码中,我们首先加载正、负样本图像,并分别提取 HOG 特征和 LBP 特征,然后将两个特征向量进行拼接,得到最终的特征向量。然后,我们使用 SVM 分类器对数据进行训练。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值