使用したライブラリ
【画像処理100本ノック】独自の画像入出力クラスを作る
【画像処理100本ノックに挑戦】独自の行列クラスを作る
Q.29. アフィン変換(拡大縮小)
アフィン変換を用いて、(1)x方向に1.3倍、y方向に0.8倍にリサイズせよ。
また、(2) (1)の条件に加えて、x方向に+30、y方向に-30だけ平行移動を同時に実現せよ。
これも行列演算が出来れば簡単です。座標をint型にキャストしているだけなので、画質が重要であればバイリニア補間等すべきでしょう。std::roundした方がよかったか(最近傍補間)。
int main()
{
PPM ppm("imori.pnm");
int width = ppm.Get_width();
int height = ppm.Get_height();
double a=1.3, b=0, c=0, d=0.8, tx=30, ty=-30;
Matrix A(2, 2);
A.set({
d/(a*d-b*c),-b/(a*d-b*c),
-c / (a * d - b * c),a / (a * d - b * c)
});
int Width = width * 1.3;
int Height = height * 0.8;
PPM ppm2(Width, Height);
for(int i=0; i<Width; i++)
for (int j = 0; j < Height; j++)
{
ppm2(i, j, 'r') = 0;
ppm2(i, j, 'g') = 0;
ppm2(i, j, 'b') = 0;
}
for(int i=0; i<Width; i++)
for (int j = 0; j < Height; j++)
{
Matrix X2(2);
X2.set({
(double)i,
(double)j
});
Matrix X0 = A * X2;
int i0= X0(0, 0)-tx;
int j0 = X0(1, 0)-ty;
if (0 <= i0 && i0 < width && 0 <= j0 && j0 < height)
{
ppm2(i, j, 'r') = ppm(i0, j0, 'r');
ppm2(i, j, 'g') = ppm(i0, j0, 'g');
ppm2(i, j, 'b') = ppm(i0, j0, 'b');
}
}
ppm2.Flush("out.ppm");
return 0;
}