0

当 a=-0.5 像往常一样时,我正在尝试使用下一个公式来实现三次插值方法。

我的线性插值和最近邻插值效果很好,但由于某种原因,三次插值因白色像素而失败,有时会将它们变成绿松石色,有时会弄乱另一种颜色。

例如使用旋转:(注意:请仔细查看右图,您会发现问题) 在此处输入图像描述

另一个具有更多黑色像素的示例。它几乎看起来很完美,但看狗的舌头。(强烈的白色像素再次变成绿松石色) 在此处输入图像描述

您可以看到我的线性插值实现效果很好:

由于实际旋转有效,我想我在代码中有一个我没有注意到的小错误,或者可能是数字错误或双/浮点错误。需要注意的是,我正常读取图像并将目标图像存储如下:

cv::Mat img = cv::imread("../dogfails.jpeg");
cv::Mat rotatedImageCubic(img.rows,img.cols,CV_8UC3);

说明:

  1. 在我的三次插值函数中,srcPoint(newX 和 newY)是逆变换的“着陆点”。

  2. 在我的逆变换中,我没有使用像素的矩阵乘法,现在我只是使用旋转公式。这对于“数字错误”可能很重要。例如:

    rotatedX = x * cos(angle * toRadian) + y * sin(angle * toRadian);
    rotatedY = x * (-sin(angle * toRadian)) + y * cos(angle * toRadian);
    

这是我的三次插值代码

double cubicEquationSolver(double d,double a) {
    d = abs(d);
    if( 0.0 <= d  && d <= 1.0) {
        double score = (a + 2.0) * pow(d, 3.0) - ((a + 3.0) * pow(d, 2.0)) + 1.0;
        return score;
    }
    else if(1 < d && d <= 2) {
        double score = a * pow(d, 3.0) - 5.0*a * pow(d, 2.0) + 8.0*a * d - 4.0*a;
        return score;
    }
    else
        return 0.0;
}

void Cubic_Interpolation_Helper(const cv::Mat& src, cv::Mat& dst, const cv::Point2d& srcPoint, cv::Point2i& dstPixel) {
    double newX = srcPoint.x;
    double newY = srcPoint.y;
    double dx = abs(newX - round(newX));
    double dy = abs(newY - round(newY));

    double sumCubicBValue = 0;
    double sumCubicGValue = 0;
    double sumCubicRValue = 0;
    double sumCubicGrayValue = 0;
    double uX = 0;
    double uY = 0;

    if (floor(newX) - 1  < 0 || floor(newX) + 2  > src.cols - 1 || floor(newY) < 0 || floor(newY)  > src.rows - 1) {
        if (dst.channels() > 1)
            dst.at<cv::Vec3b>(dstPixel) = cv::Vec3b(0, 0,0);
        else
            dst.at<uchar>(dstPixel) = 0;
    }
    else {
        for (int cNeighbor = -1; cNeighbor <= 2; cNeighbor++) {
            for (int rNeighbor = -1; rNeighbor <= 2; rNeighbor++) {
                uX = cubicEquationSolver(rNeighbor + dx, -0.5);
                uY = cubicEquationSolver(cNeighbor + dy, -0.5);
                if (src.channels() > 1) {
                    sumCubicBValue = sumCubicBValue + (double) src.at<cv::Vec3b>(
                            cv::Point2i(round(newX) + rNeighbor, cNeighbor + round(newY)))[0] * uX * uY;
                    sumCubicGValue = sumCubicGValue + (double) src.at<cv::Vec3b>(
                            cv::Point2i(round(newX) + rNeighbor, cNeighbor + round(newY)))[1] * uX * uY;
                    sumCubicRValue = sumCubicRValue + (double) src.at<cv::Vec3b>(
                            cv::Point2i(round(newX) + rNeighbor, cNeighbor + round(newY)))[2] * uX * uY;
                } else {
                    sumCubicGrayValue = sumCubicGrayValue + (double) src.at<uchar>(
                            cv::Point2i(round(newX) + rNeighbor, cNeighbor + round(newY))) * uX * uY;
                }
            }
        }
        if (dst.channels() > 1)
            dst.at<cv::Vec3b>(dstPixel) = cv::Vec3b((int) round(sumCubicBValue), (int) round(sumCubicGValue),
                                                    (int) round(sumCubicRValue));
        else
            dst.at<uchar>(dstPixel) = sumCubicGrayValue;
    }

我希望这里的人能够帮助我,谢谢!

4

0 回答 0