4、基于像素区域关系:共分三种情况,图像放大时类似于双线性插值,图像缩小(x轴、y轴同时缩小)又分两种情况,此情况下可以避免波纹出现。
- cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 3);
- cv::imwrite("area_2.jpg", matDst2);
- double inv_scale_x = 1. / scale_x;
- double inv_scale_y = 1. / scale_y;
- int iscale_x = cv::saturate_cast<int>(scale_x);
- int iscale_y = cv::saturate_cast<int>(scale_y);
- bool is_area_fast = std::abs(scale_x - iscale_x) < DBL_EPSILON && std::abs(scale_y - iscale_y) < DBL_EPSILON;
- if (scale_x >= 1 && scale_y >= 1) //zoom out
- {
- if (is_area_fast) //integer multiples
- {
- for (int j = 0; j < matDst1.rows; ++j)
- {
- int sy = j * scale_y;
- for (int i = 0; i < matDst1.cols; ++i)
- {
- int sx = i * scale_x;
- matDst1.at<cv::Vec3b>(j, i) = matSrc.at<cv::Vec3b>(sy, sx);
- }
- }
- cv::imwrite("area_1.jpg", matDst1);
- return 0;
- }
- for (int j = 0; j < matDst1.rows; ++j)
- {
- double fsy1 = j * scale_y;
- double fsy2 = fsy1 + scale_y;
- double cellHeight = cv::min(scale_y, matSrc.rows - fsy1);
- int sy1 = cvCeil(fsy1), sy2 = cvFloor(fsy2);
- sy2 = std::min(sy2, matSrc.rows - 1);
- sy1 = std::min(sy1, sy2);
- float cbufy[2];
- cbufy[0] = (float)((sy1 - fsy1) / cellHeight);
- cbufy[1] = (float)(std::min(std::min(fsy2 - sy2, 1.), cellHeight) / cellHeight);
- for (int i = 0; i < matDst1.cols; ++i)
- {
- double fsx1 = i * scale_x;
- double fsx2 = fsx1 + scale_x;
- double cellWidth = std::min(scale_x, matSrc.cols - fsx1);
- int sx1 = cvCeil(fsx1), sx2 = cvFloor(fsx2);
- sx2 = std::min(sx2, matSrc.cols - 1);
- sx1 = std::min(sx1, sx2);
- float cbufx[2];
- cbufx[0] = (float)((sx1 - fsx1) / cellWidth);
- cbufx[1] = (float)(std::min(std::min(fsx2 - sx2, 1.), cellWidth) / cellWidth);
- for (int k = 0; k < matSrc.channels(); ++k)
- {
- matDst1.at<cv::Vec3b>(j, i)[k] = (uchar)(matSrc.at<cv::Vec3b>(sy1, sx1)[k] * cbufx[0] * cbufy[0] +
- matSrc.at<cv::Vec3b>(sy1 + 1, sx1)[k] * cbufx[0] * cbufy[1] +
- matSrc.at<cv::Vec3b>(sy1, sx1 + 1)[k] * cbufx[1] * cbufy[0] +
- matSrc.at<cv::Vec3b>(sy1 + 1, sx1 + 1)[k] * cbufx[1] * cbufy[1]);
- }
- }
- }
- cv::imwrite("area_1.jpg", matDst1);
- return 0;
- }
- //zoom in,it is emulated using some variant of bilinear interpolation
- for (int j = 0; j < matDst1.rows; ++j)
- {
- int sy = cvFloor(j * scale_y);
- float fy = (float)((j + 1) - (sy + 1) * inv_scale_y);
- fy = fy <= 0 ? 0.f : fy - cvFloor(fy);
- short cbufy[2];
- cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);
- cbufy[1] = 2048 - cbufy[0];
- for (int i = 0; i < matDst1.cols; ++i)
- {
- int sx = cvFloor(i * scale_x);
- float fx = (float)((i + 1) - (sx + 1) * inv_scale_x);
- fx = fx < 0 ? 0.f : fx - cvFloor(fx);
- if (sx < 0) {
- fx = 0, sx = 0;
- }
- if (sx >= matSrc.cols - 1) {
- fx = 0, sx = matSrc.cols - 2;
- }
- short cbufx[2];
- cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);
- cbufx[1] = 2048 - cbufx[0];
- for (int k = 0; k < matSrc.channels(); ++k)
- {
- matDst1.at<cv::Vec3b>(j, i)[k] = (matSrc.at<cv::Vec3b>(sy, sx)[k] * cbufx[0] * cbufy[0] +
- matSrc.at<cv::Vec3b>(sy + 1, sx)[k] * cbufx[0] * cbufy[1] +
- matSrc.at<cv::Vec3b>(sy, sx + 1)[k] * cbufx[1] * cbufy[0] +
- matSrc.at<cv::Vec3b>(sy + 1, sx + 1)[k] * cbufx[1] * cbufy[1]) >> 22;
- }
- }
- }
- cv::imwrite("area_1.jpg", matDst1);