帧内模板匹配预测TMP

帧内模拟匹配预测(Intra template matching prediction,Intra TMP)是一种特殊的帧内预测模型,和IBC类似,TMP使用当前帧已重建部分作为预测。不过和IBC的区别在于,它不是在重建区域中搜索与当前块最相近的块作为预测,而是搜索和当前块的L型模板最匹配的块。


如上图所示,当前块左侧和上方像素形成了一个L型的模板,TMP使用该模板在重建区域搜索最匹配的L型模板,然后使用这个最匹配的L型模板所包围的块作为当前块的预测块。TMP工具适合屏幕内容场景,且进行模板搜索时使用SAD寻找最优模板。

模板搜索的区域在当前帧重建区域,只要包括4个部分:

  • R1:当前CTU

  • R2:左上角CTU

  • R3:上方CTU

  • R4:左侧CTU

每个区域的搜索范围(SearchRange_w, SearchRange_h)和块的大小 (BlkW, BlkH)成正比,从而使得每个像素的SAD计算量固定。

SearchRange_w = a * BlkW

SearchRange_h = a * BlkH

a是一个常数,在复杂度和增益间取得平衡,通常a=5。

TMP用于尺寸小于等于64的CU,需要在CU上传输一个标志位表示是否使用TMP。

下面是TMP在all intra和RA配置下的测试结果,可见TMP在class F和TGM序列上表现更好,因此TMP更适合屏幕内容。

参考文献

[1]Karam Naser,Fabrice Le Leannec,Tangi Poirier,Franck Galpin,JVET-U0048,"Evaluation ofTemplate Matching Prediction for VVC",Jan. 2021

[2]K. Naser,Tangi Poirier,Fabrice Le Léannec,Gaelle Martin-Cocher,JVET-V0130,"EE2: Intra TemplateMatching"

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是不使用OpenCV库,纯C++实现的NCC模板匹配的代码实现: ```cpp #include <iostream> #include <cmath> #include <ctime> #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int MAXN = 1005; const double PI = acos(-1.0); int n, m; double a[MAXN][MAXN], b[MAXN][MAXN]; double cosb, sinb; // 对图像进行旋转变换 void rotate(double& x, double& y, double sinb, double cosb) { double x1 = x * cosb + y * sinb; double y1 = -x * sinb + y * cosb; x = x1; y = y1; } // 计算图像的均值 double mean(double a[][MAXN], int n, int m) { double sum = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) sum += a[i][j]; return sum / (n * m); } // 计算归一化互相关系数 double NCC(int x, int y) { double sum = 0, sum1 = 0, sum2 = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { double xx = i - x, yy = j - y; rotate(xx, yy, sinb, cosb); // 对坐标进行旋转变换 if (xx >= 0 && xx < n && yy >= 0 && yy < m) { sum += a[i][j] * b[int(xx)][int(yy)]; sum1 += a[i][j] * a[i][j]; sum2 += b[int(xx)][int(yy)] * b[int(xx)][int(yy)]; } } } return sum / sqrt(sum1 * sum2); } // 计算最大匹配值及其位置 double match(int& x, int& y) { double res = -1e9; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { double tmp = NCC(i, j); if (tmp > res) { res = tmp; x = i; y = j; } } } return res; } int main() { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) scanf("%lf", &a[i][j]); int p, q; scanf("%d%d", &p, &q); for (int i = 0; i < p; i++) for (int j = 0; j < q; j++) scanf("%lf", &b[i][j]); // 对模板图像进行均值化 double meanb = mean(b, p, q); for (int i = 0; i < p; i++) for (int j = 0; j < q; j++) b[i][j] -= meanb; // 对模板图像进行旋转变换 double theta = 2 * PI / 360; double angle = -30; sinb = sin(angle * theta), cosb = cos(angle * theta); double x1 = 0, y1 = 0, x2 = p - 1, y2 = q - 1; rotate(x1, y1, sinb, cosb); rotate(x2, y2, sinb, cosb); int np = ceil(max(max(x1, x2), double(p))), nq = ceil(max(max(y1, y2), double(q))); for (int i = 0; i < np; i++) { for (int j = 0; j < nq; j++) { double x = i, y = j; rotate(x, y, sinb, cosb); if (x >= 0 && x < p && y >= 0 && y < q) b[i][j] = b[int(x)][int(y)]; else b[i][j] = 0; } } // 对搜索图像进行均值化 double meana = mean(a, n, m); for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) a[i][j] -= meana; int x, y; double res = match(x, y); // 计算最大匹配值及其位置 printf("最大匹配值:%lf\n", res); // 在搜索图像中标记匹配位置 for (int i = x - p / 2; i <= x + p / 2; i++) for (int j = y - q / 2; j <= y + q / 2; j++) a[i][j] = 255; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) printf("%.2lf%c", a[i][j], j == m - 1 ? '\n' : ' '); return 0; } ``` 该代码实现了NCC模板匹配的核心算法,包括模板图像的旋转变换、归一化互相关系数的计算、最大匹配值及其位置的计算等。需要注意的是,该代码中使用了角度为-30°的旋转变换,可以根据需要进行调整。 由于该代码没有使用OpenCV库,因此在处理大尺寸图像和模板时可能会比较慢。可以使用多线程等技术来加速计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值