二维变换中的双线性插值Qt

时间:2017-08-27 14:02:46

标签: c++ qt graphics 2d interpolation

我目前正在Qt中进行2D变换(平移,缩放,剪切和旋转)。我对双线性插值有一个问题,我想用它来覆盖黑色像素'在输出图像中。我使用矩阵计算来获得输入图像像素的新坐标。然后我使用反向矩阵计算来检查输入图像的哪个像素响应输出像素。结果是我用于插值的一些浮点数。我检查四个相邻点并计算输出像素的值(颜色)。我已经手动检查了我的计算结果'他们似乎很好。

有人能找到该代码中的任何错误吗? (我删除了负责界面的代码部分,如滑块)。

Geometric::Geometric(QWidget* parent) : QWidget(parent) {
    resize(1000, 800);
    displayLogoDefault = true;

    a = shx = shy = x0 = y0 = 0;
    scx = scy = 1;
    tx = ty = 0;
    x = 200, y = 200;
    paintT = paintSc = paintR = paintShx = paintShy = false;

    img = new QImage(600,600,QImage::Format_RGB32);
    img2 = new QImage("logo.jpeg");
}
Geometric::~Geometric() {
    delete img;
    delete img2;
    img = NULL;
    img2 = NULL;
}

void Geometric::makeChange() {
    displayLogoDefault = false;

    // iteration through whole input image
    for(int i = 0; i < img2->width(); i++) {
        for(int j = 0; j < img2->height(); j++) {

            // calculate new coordinates basing on given 2D transformations values 
            //I calculated that formula eariler by multiplying/adding matrixes
            x = cos(a)*scx*(i-x0) - sin(a)*scy*(j-y0) + shx*sin(a)*scx*(i-x0) + shx*cos(a)*scy*(j-y0);
            y = shy*(x) + sin(a)*scx*(i-x0) + cos(a)*scy*(j-y0);

            // tx and ty goes for translation. scx and scy for scaling
            // shx and shy for shearing and a is angle for rotation

            x += (x0 + tx);
            y += (y0 + ty);

            if(x >= 0 && y >= 0 && x < img->width() && y < img->height()) {
                // reverse matrix calculation formula to find proper pixel from input image
                float tmx = x - x0 - tx;
                float tmy = y - y0 - ty;
                float recX = 1/scx * ( cos(-a)*( (tmx + shx*shy*tmx - shx*tmx) ) + sin(-a)*( shy*tmx - tmy ) ) + x0 ;
                float recY = 1/scy * ( sin(-a)*(tmx + shx*shy*tmx - shx*tmx) - cos(-a)*(shy*tmx-tmy) ) + y0;


                // here the interpolation starts. I calculate the color basing on four points from input image
                // that points are taken from the reverse matrix calculation
                float a = recX - floorf(recX);
                float b = recY - floorf (recY);

                if(recX + 1 > img2->width()) recX -= 1;
                if(recY + 1 > img2->height()) recY -= 1;

                QColor c1 = QColor(img2->pixel(recX, recY));
                QColor c2 = QColor(img2->pixel(recX + 1, recY));
                QColor c3 = QColor(img2->pixel(recX , recY + 1));
                QColor c4 = QColor(img2->pixel(recX + 1, recY + 1));

                float colR = b * ((1.0 - a) * (float)c3.red() + a * (float)c4.red()) + (1.0 - b) * ((1.0 - a) * (float)c1.red() + a * (float)c2.red());
                float colG = b * ((1.0 - a) * (float)c3.green() + a * (float)c4.green()) + (1.0 - b) * ((1.0 - a) * (float)c1.green() + a * (float)c2.green());
                float colB = b * ((1.0 - a) * (float)c3.blue() + a * (float)c4.blue()) + (1.0 - b) * ((1.0 - a) * (float)c1.blue() + a * (float)c2.blue());            
                if(colR > 255) colR = 255; if(colG > 255) colG = 255; if(colB > 255) colB = 255;
                if(colR < 0 ) colR = 0; if(colG < 0 ) colG = 0; if(colB < 0 ) colB = 0;
                paintPixel(x, y, colR, colG, colB);
            }
        }
    }
    // x0 and y0 are the starting point of image
    x0 = abs(x-tx);
    y0 = abs(y-ty);
    repaint();
}

// function painting a pixel. It works directly on memory
void Geometric::paintPixel(int i, int j, int r, int g, int b) {
    unsigned char *ptr = img->bits();
    ptr[4 * (img->width() * j + i)] = b;
    ptr[4 * (img->width() * j + i) + 1] = g;
    ptr[4 * (img->width() * j + i) + 2] = r;

}

void Geometric::paintEvent(QPaintEvent*) {
    QPainter p(this);
    p.drawImage(0, 0, *img);
    if (displayLogoDefault == true) p.drawImage(0, 0, *img2);
}

0 个答案:

没有答案