调代码 调晕菜了 ~!!!
// 遍历块, 求合、求均值
for (int channel = 0; channel < 2; channel++){
for (int i = 0; i < 3; i++){
for (int j = 0; j < 4; j++){
cout << "i * j : " << i << " " << j << endl;
int blockSum = 0;
double absDiffSum = 0.0;
for (int k = 0; k < blockH; k++){
for (int h = 0; h < blockW; h++){
//cout << "k * h : " << k << " " << h << endl;
if ((i == 0) && (j == 3)){
cout << "row*col : " << i << " * " << j << " k * h : " << k << " * " << h << endl;
cout << "ele axis : " << validRowsT + i * blockH + k << " , " << j * blockW + h << endl;
cout << "channel : " << channel << endl;
}
uchar element = ycbr.at<Vec4b>(validRowsT + i * blockH + k, j * blockW + h)[channel + 1];
blockSum = element + blockSum;
}
}
blockMean[channel][4 * i + j] = double(blockSum / (blockW * blockH));
cout <<"mean : " <<blockMean[channel][4 * i + j] << endl;
}
}
}
调试代码的两大力器:中断、注释
1、多设置几个断点,快速找出是哪行代码出的鬼,
2、循环中,不方便设置断点的,设置条件断点,
3、条件断点仍然解决不了的,采用注释,直接哪里可能出问题 注释掉哪里 。
最终通过注释的方式 找到出鬼的代码行
for (int k = 0; k < blockH; k++){
for (int h = 0; h < blockW; h++){
//cout << "k * h : " << k << " " << h << endl;
if ((i == 0) && (j == 3)){
cout << "row*col : " << i << " * " << j << " k * h : " << k << " * " << h << endl;
cout << "ele axis : " << validRowsT + i * blockH + k << " , " << j * blockW + h << endl;
cout << "channel : " << channel << endl;
cout << ycbr.rows << ycbr.cols << endl;
}
uchar element = ycbr.at<Vec4b>(validRowsT + i * blockH + k, j * blockW + h)[channel+1]; // 问题代码
blockSum = element + blockSum;
}
}
将问题代码 ,用下面的代码行代替,可以跑通,但是不是想要的逻辑。 换其它方式
for (int k = 0; k < blockH; k++){
for (int h = 0; h < blockW; h++){
//cout << "k * h : " << k << " " << h << endl;
if ((i == 0) && (j == 3)){
cout << "row*col : " << i << " * " << j << " k * h : " << k << " * " << h << endl;
cout << "ele axis : " << validRowsT + i * blockH + k << " , " << j * blockW + h << endl;
cout << "channel : " << channel << endl;
cout << ycbr.rows << ycbr.cols << endl;
}
uchar element = ycbr.at<uchar>(validRowsT + i * blockH + k, j * blockW + h);
blockSum = element + blockSum;
}
}
注释后找到代码行,具体什么原因呢??
代码行里面 逐一排查, 尤其是变量, 将对应的变量 变成常量 , 一个个 来, 老子还不信你个小鬼出来了
uchar element = ycbr.at<Vec4b>( 574 ,6750)[1];
//uchar element = ycbr.at<Vec4b>((validRowsT + i * blockH + k),( j * blockW + h))[0];
blockSum = element + blockSum;
将 channel换成常量 0 、1 没改变
将坐标参数 变成对应的报错的常数 (574,6750),结果 输出结果有变化了
说明
cout << "ycbr.rows: " << ycbr.rows << "ycbr.cols : " <<ycbr.cols << endl;
for (int i = 0; i < ycbr.rows;i++){
for (int j = 0; j < ycbr.cols;j++){
int element = ycbr.at<Vec4b>(574, 6750)[1]; // (574 ,6750)
}
}
ycbr 为4通道变量(问题在这里,实则不然,是3通道变量), 行数为 4500, 列数为 9000
然后在用 动态地址计算方式 进行 像素访问操作时,出现报错, 当j达到6570时报错。
总结:
1、 Mat 用imread 读入图像时,格式为BGR格式,是3通道变量, 输出 Mat.channels==3, 应该用 Mat.at<Vec3b>(i,j)[channel]
2、rgb ,定义为CV_8UC4,由BGR图像 通过cvCvtColor函数转化而来, rgb.channels==4, -----------Vec4b
3、ycbr ,定义为CV_8UC4, 有rgb格式图像通过cvCvtColor函数转化而来 ,ycbr.channels==3, -----------Vec3b