球面化濾鏡將平面圖像映射到球面上再投影回平面,產生凹陷/凸出的立體視覺效果。

以圖像中心為球心,半徑 R = min(width, height)/2。像素 (x, y) 相對中心極坐標 (r0, θ)。球面映射關係:
r = R * sin(r0 / R * K),其中 K = π/2 控制映射範圍(r0 ∈ [0, R] → r ∈ [0, R])。
α = 0.75 為壓縮係數(原代碼未直接用,可能殘留)。
(x, y),計算相對中心 (x0, y0)。r0 = sqrt(x0² + y0²), θ = atan2(y0, x0)。r = R * sin(r0 / R * K)(r ≤ r0 產生凹陷)。new_x = r * cos(θ) + cx, new_y = cy - r * sin(θ)。#define pi 3.1415926
int main() {
Mat Img = imread("4.jpg");
Mat Img_out(Img.size(), CV_8UC3);
int width = Img.cols, height = Img.rows;
Point Center(width/2, height/2);
float R = min(width, height) / 2.0f;
float K = pi / 2;
float alpha = 0.75f; // 可作為強度參數
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
float x0 = x - Center.x;
float y0 = Center.y - y;
float Dis = x0*x0 + y0*y0;
float r0 = sqrt(Dis);
float theta = atan2(y0, x0 + 1e-5);
// 球面映射核心公式
float r = R * sin(r0 / R * K);
float new_x = r * cos(theta) + Center.x;
float new_y = Center.y - r * sin(theta);
// 邊界保護
if (new_x < 0) new_x = 0;
if (new_x >= width-1) new_x = width-2;
if (new_y < 0) new_y = 0;
if (new_y >= height-1) new_y = height-2;
// 雙線性插值
int x1 = (int)new_x, y1 = (int)new_y;
float p = new_x - x1, q = new_y - y1;
for (int k = 0; k < 3; ++k) {
Img_out.at(y, x)[k] =
(1-p)*(1-q)*Img.at(y1, x1)[k] +
p*(1-q)*Img.at(y1, x1+1)[k] +
(1-p)*q*Img.at(y1+1, x1)[k] +
p*q*Img.at(y1+1, x1+1)[k];
}
}
}
imshow("Sphere", Img_out);
imwrite("Out.jpg", Img_out);
waitKey();
return 0;
}
r = R * tan(r0 / R * K') 或 r = r0 / cos(...)(需限制定義域)。strength ∈ [0,1],r = r0 + strength * (R*sin(...) - r0)。sin/cos 查找表(角度量化 0.1°)。remap + 预計算映射圖 mapx, mapy,利用 SIMD 加速。