在C ++中,是否存在使用GDAL库对给定矩形(xmin,ymin,xmax,ymax)内具有一定值的所有像素进行计数的函数?还是我必须阅读每个块并逐个像素地计数它们?我已经搜索过,但只发现了一些这样做的Python脚本。
我自己完成了操作(这是一个布尔栅格-0/1-我正在计算“ 1”像素),但是结果与GRASS GIS r.report函数(通过QGIS)给出的结果不同。
long long openTIF(string ftif,double x0,double y0,double x1,double y1) {
long long sum = 0;
GDALDataset *poDataset;
GDALAllRegister();
poDataset = (GDALDataset*)GDALOpen(ftif.c_str(),GA_ReadOnly);
if (poDataset == NULL) {
cout << "Error reading raster '" << ftif << "'\n";
exit(1);
}
int tx=poDataset->GetRasterXSize(),
ty=poDataset->GetRasterYSize();
double geoTransf[6], rx0=0, ry0=0, rx1=0, ry1=0;
if (poDataset->GetGeoTransform(geoTransf) == CE_None) {
rx0 = geoTransf[0];
ry0 = geoTransf[3]-ty*geoTransf[1];
rx1 = geoTransf[0]-tx*geoTransf[5];
ry1 = geoTransf[3];
} else {
exit(2);
}
int nBlockXSize,nBlockYSize;
GDALRasterBand *poBand;
poBand = poDataset->GetRasterBand(1);
poBand->GetBlockSize(&nBlockXSize,&nBlockYSize);
uint32_t i;
int y,
col0 = round((rx0-x0)/geoTransf[5]),
col1 = round((rx0-x1)/geoTransf[5]),
row0 = round((ry1-y1)/geoTransf[1]),
row1 = round((ry1-y0)/geoTransf[1]);
CPLErr error;
uint8_t *data = (uint8_t*)CPLMalloc(nBlockXSize*nBlockYSize);
GDALDataType type = poBand->GetRasterDataType();
if (type == GDT_Byte) {
cout << "Byte" << endl;
}
for (y=row0; y<row1; y++) {
error = poBand->ReadBlock(0,y,data);
if (error > 0) {
cout << "Error reading data block.\n";
exit(3);
}
for (i=col0; i<col1; i++) {
sum += (uint8_t)data[i];
}
}
CPLFree(data);
return sum;
}
对于该给定的栅格和给定的坐标(精度%.8f),GRASS GIS r.report函数报告的28096011像素值为1,而我的总和为28094709(差= -1302)。与其他坐标,r.report给出5605458,我的总和给出5604757(差= -701)。知道会发生什么吗?
编辑:由于我的总和总是小于GRASS GIS r.report,因此我包括了最后一行和最后一列,更改了行
for (y=row0; y<row1; y++) {
for (i=col0; i<col1; i++) {
到
for (y=row0; y<=row1; y++) {
for (i=col0; i<=col1; i++) {
但是现在,使用另一组坐标,r.report得到249707,而我的总和得到250157(差= +450)。
答案 0 :(得分:3)
这看起来像是舍入错误,您需要舍入列和行索引。如果将每个栅格像素都视为矩形区域,则更容易推理。例如,栅格的第一个像素从(x, y)
到(x + width, y + height)
。
rx = geoTransf[0];
rx_size = geoTransf[1]; // you got geoTransf[1] and geoTransf[5] swapped!
ry = geoTransf[3];
ry_size = geoTransf[5];
// assert, that geoTrans[2] and geoTrans[4] are zero
col_first = floor((x0 - rx) / rx_size));
col_last = floor((x1 - rx) / rx_size));
row_first = floor((y0 - ry) / ry_size));
row_last = floor((y1 - ry) / ry_size));
for (int y = row_first; y <= row_last; ++y) {
poBand->ReadBlock(col_first, y, data);
for (int x = 0; x <= col_last - col_first; ++x) {
data[x];
}
}