在做通过鼠标设置ROI并对其进行阈值化功能的时候,发现处理的图像区域总是与我用鼠标设置的区域上下颠倒,源代码如下:
for (UINT i=rc.bottom; i<rc.top; i++)
{
for (UINT j=3*rc.left; j<3*rc.right; j=j+3)
{
//在BMP图片中颜色顺序为BGR
//color=red*0.299+green*0.587+blue*0.144;
*(pImgData + i*lineByte + j) = (*(pImgData + i*lineByte + j))*0.114 +
(*(pImgData + i*lineByte + j + 1))*0.587 + (*(pImgData + i*lineByte + j + 2))*0.299;
int blue = *(pImgData + i*lineByte + j);
if (blue < thresholValue)
{
*(pImgData + i*lineByte + j) = 0;
}
else
{
*(pImgData + i*lineByte + j) = 255;
}
*(pImgData + i*lineByte + j + 1) = (*(pImgData + i*lineByte + j));
int green = *(pImgData + i*lineByte + j + 1);
if (green < thresholValue)
{
*(pImgData + i*lineByte + j + 1) = 0;
}
else
{
*(pImgData + i*lineByte + j + 1) = 255;
}
*(pImgData + i*lineByte + j + 2) = (*(pImgData + i*lineByte + j));
int red = *(pImgData + i*lineByte + j + 2);
if (red < thresholValue)
{
*(pImgData + i*lineByte + j + 2) = 0;
}
else
{
*(pImgData + i*lineByte + j + 2) = 255;
}
}
}
其中rc为是我在MFC定义的一个CRect的类,其矩形的始末点由鼠标左键按下和左键抬起的位置的坐标点,这个鼠标的坐标点实际上是使用了MFC中的CPoint类的坐标,该坐标的坐标系原点在窗口的左上角。正在当我百思不得其解的时候,我在foreverhuylee《位图结构解析》博文中看出了点端倪,原因如下:
DIB位图也有两种形式,即:底到上型DIB(bottom-up),和顶到下型DIB(top-down)。底到上型DIB的原点(origin)在图像的左下角,而顶到下型DIB的原点在图像的左上角。如果DIB的高度值(由BITMAPINFOHEADER结构中的biHeight成员标识)是一个正值,那么就表明这个DIB是一个底到上型DIB,如果高度值是一个负值,那么它就是一个顶到下型DIB。注意:顶到下型的DIB位图是不能被压缩的。
由上可知,其实我使用到的BMP图片都是属于“底到上型”的,即其数据读取都是从下到上,由左至右的,说白了就是其坐标原点在左下角和我们用CRect截取的矩形坐标(原点在左上角)是不同的,即X轴坐标相同,而Y轴不同,用图片的高度减去矩形的高度就能让两者的坐标同步,故修改后的代码如下:
for (UINT i=(bmpInfo.biHeight-rc.bottom); i<(bmpInfo.biHeight-rc.top); i++)
{
for (UINT j=3*rc.left; j<3*rc.right; j=j+3)
{
//在BMP图片中颜色顺序为BGR
//color=red*0.299+green*0.587+blue*0.144;
*(pImgData + i*lineByte + j) = (*(pImgData + i*lineByte + j))*0.114 +
(*(pImgData + i*lineByte + j + 1))*0.587 + (*(pImgData + i*lineByte + j + 2))*0.299;
int blue = *(pImgData + i*lineByte + j);
if (blue < thresholValue)
{
*(pImgData + i*lineByte + j) = 0;
}
else
{
*(pImgData + i*lineByte + j) = 255;
}
*(pImgData + i*lineByte + j + 1) = (*(pImgData + i*lineByte + j));
int green = *(pImgData + i*lineByte + j + 1);
if (green < thresholValue)
{
*(pImgData + i*lineByte + j + 1) = 0;
}
else
{
*(pImgData + i*lineByte + j + 1) = 255;
}
*(pImgData + i*lineByte + j + 2) = (*(pImgData + i*lineByte + j));
int red = *(pImgData + i*lineByte + j + 2);
if (red < thresholValue)
{
*(pImgData + i*lineByte + j + 2) = 0;
}
else
{
*(pImgData + i*lineByte + j + 2) = 255;
}
}
}
此时,已经完成我最初对程序的设想,即使用鼠标设置ROI并对该区域进行阈值化。