[英]Convert 8x8 Matrix into flatten vector using zigzag scan
因此,我需要使用 zig zag 扫描将 8x8 的 opencv mat 转换为扁平矢量,如图所示。
我明白它应该做什么,我想我已经完成了前半部分的实现,但是当我尝试将值设置为向量时收到错误。
std::vector<float> *ZigZagScanner::scan(cv::Mat &input) {
std::vector<float> *output = new std::vector<float>();
// TODO Traverse the input in a zigzag scan, and store the result in output
//set row and column start values to zero, set increment flag to false
// TODO Traverse the input in a zigzag scan, and store the result in output
//set row and column start values to zero, set increment flag to false
int row, col = 0;
bool increment = false;
//create nest for loops to traverse through the first half of the matrix in a zig zag fashion
for(int y = 1; y <= 8; ++y){
for(int x = 0; x < y; ++x){
//add the current row and column to the flatten vector
//ERROR HERE
cv::Rect rect = cv::Rect(y,x, 8, 8);
output->push_back(new cv::Mat(input, rect));
if(x + 1 == y){
break;
}
//when the increment flag is true increase the row and decrease the column
if(increment == true){
++row, --col;
}
else{
--row, ++col;
}
}
//if y gets to out of bounds break the loop
if(y == 8){
break;
}
//if the increment flag is true then increment the row and switch the flag, otherwise increment the column and swap the flag
if(increment == true){
++row, increment = false;
}
else{
++col, increment = true;
}
}
//update the columns and rows to the correct values to go through the second half of the matrix
if(row == 0){
if(col == 7){
++row;
}
else{
++col;
increment = true;
}
}
else{
if(row == 7){
++col;
}
else{
++row;
increment = false;
}
}
for(int k, j = 7; j > 0; --j){
if(j > 8){
k = 8;
}
else{
k = j;
}
for(int i = 0; i < k; i++){
//ERROR HERE AS WELL
cv::Rect rect = cv::Rect(y,x, 8, 8);
output->push_back(new cv::Mat(input, rect));
}
}
在这一点上,我只是在努力弄清楚这部分,任何建议都意味着一吨! 返回输出; }
您的输出向量存储float
,那么您为什么要尝试将指针推到cv::Mat
那里呢?
如果您有 8x8 的浮点矩阵,只需使用.at<float>(y,x)
方法来访问input
矩阵的一个浮点值。
output->push_back(input.at<float>(y-1,x)); // -1 because you iterate in range <1,8>
您的方法似乎是您想使用Rect
作为 ROI 并将其应用于输入矩阵。 如果您想将输入Mat
区域设为 1x1 矩形,您可以:
cv::Rect roi(x,y-1,1,1); // 1x1 matrix
output->push_back( input(roi).at<float>(0,0) );
另外我不明白为什么你使用 N 个循环来制作锯齿形顺序,而不是成对的数组:
std::pair<int,int> zigZagOrder[64] = { {0,0},{1,0},{1,0},...};
然后只查找这个。
在图像处理中,每一毫秒都很重要,不要浪费时间在做锯齿形顺序的花哨方式上。
很抱歉没有提供 C/C++ 中的代码,但我很确定您可以毫无问题地将其转换为 C/C++,因为我没有使用任何特定于 python 的东西:
#!/usr/bin/env python
N = 4
i, j = 0, 0
while j != (N-1) :
print i, j
if i == 0 and (j & 1) :
j += 1
continue
if j == 0 and (i & 1) == 0:
i += 1
continue
if (i ^ j) & 1 :
i -= 1
j += 1
continue
if (i ^ j) & 1 == 0 :
i += 1
j -= 1
continue
while i != (N-1) or j != (N-1) :
print i, j
if i == (N-1) and (j & 1) :
j += 1
continue
if j == (N-1) and (i & 1) == 0 :
i += 1
continue
if (i ^ j) & 1 :
i -= 1
j += 1
continue
if (i ^ j) & 1 == 0 :
i += 1
j -= 1
continue
print i, j # last square
输出:
0 0
1 0
0 1
0 2
1 1
2 0
3 0
2 1
1 2
0 3
1 3
2 2
3 1
3 2
2 3
3 3
遍历对角线,然后遍历对角线元素。 您只需要简单的数学运算即可计算元素索引:
const int n = 8;
for (int diag = 0; diag < 2 * n - 1; ++diag) {
const auto i_min = std::max(0, diag - n + 1);
const auto i_max = i_min + std::min(diag, 2 * (n - 1) - diag);
for (auto i = i_min; i <= i_max; ++i) {
const auto row = diag % 2 ? i : (diag - i);
const auto col = diag % 2 ? (diag - i) : i;
// (row, col) is current element
}
}
您可以强制编译器展开所有这些循环:
namespace impl {
template<int offset, int... is>
constexpr auto offset_sequence(std::integer_sequence<int, is...>) {
return std::integer_sequence<int, (is + offset)...>{};
}
template<int diag, class Fn, int... is>
constexpr void zigzag2(Fn fn, std::integer_sequence<int, is...>) {
(fn(diag % 2 ? is : diag - is, diag % 2 ? diag - is : is), ...);
}
template<int size, class Fn, int... diags>
constexpr void zigzag1(Fn fn, std::integer_sequence<int, diags...>) {
(zigzag2<diags>(fn, offset_sequence<std::max(0, diags - size + 1)>(
std::make_integer_sequence<int,
1 + std::min(diags, 2 * (size - 1) - diags)>{})), ...);
}
}
template<int size, class Fn>
constexpr void zigzag(Fn fn) {
impl::zigzag1<size>(fn, std::make_integer_sequence<int, 2 * size - 1>{});
}
template<int size>
constexpr auto zigzag_indices() {
std::array<std::pair<int, int>, size * size> arr{};
auto it = arr.begin();
zigzag<size>([&it](int x, int y) { it->first = x; it->second = y; ++it; });
assert(it == arr.end());
return arr;
}
zigzag<n>()
生成给定功能对象的n * n
调用,没有循环和分支。 zigzag_indices()
生成一组索引对(想法取自rafix07的答案)。 这个函数是constexpr
,所以这个数组可以在编译时生成。
用法示例:
// 1.
zigzag<8>([&](int x, int y) {
output->push_back(input.at<float>(y, x));
});
// 2.
constexpr auto indices = zigzag_indices<8>();
for (auto i : indices) {
output->push_back(input.at<float>(i.second, i.first));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.