
將圖像像素從平面座標映射到球面座標,產生凸出的球面視覺效果。核心數學:
R = min(寬, 高)/2。(x, y),計算其相對中心向量 (x0, y0)。Dis = x0² + y0², theta = atan2(y0, x0)。radius = asin(sqrt(Dis)/R) * R / K(K = π/2 控制曲率)。new_x = radius * cos(theta), new_y = radius * sin(theta)。#include#include using namespace cv; using namespace std; #define PI 3.1415926 int main() { Mat src = imread("4.jpg"); if (src.empty()) return -1; Mat dst(src.size(), CV_8UC3); int w = src.cols, h = src.rows; float a = h / 2.0f, b = w / 2.0f; float R = min(a, b); float K = PI / 2; Point center(w/2, h/2); float alpha = 0.75f; // 強度參數 for (int y = 0; y < h; ++y) { uchar* dstRow = dst.ptr (y); for (int x = 0; x < w; ++x) { float x0 = x - center.x; float y0 = center.y - y; // y 軸反轉 float Dis = x0*x0 + y0*y0; float theta = atan2(y0, x0 + 1e-5f); float radius = asin(sqrt(Dis) / R) * R / K; float new_x = radius * cos(theta) + center.x; float new_y = center.y - radius * sin(theta); // 邊界裁剪 new_x = max(0.0f, min(new_x, w - 2.0f)); new_y = max(0.0f, min(new_y, h - 2.0f)); int x1 = (int)new_x, y1 = (int)new_y; float p = new_x - x1, q = new_y - y1; // 雙線性插值 for (int c = 0; c < 3; ++c) { float v = (1-p)*(1-q)*src.at (y1, x1)[c] + p*(1-q)*src.at (y1, x1+1)[c] + (1-p)*q*src.at (y1+1, x1)[c] + p*q*src.at (y1+1, x1+1)[c]; dstRow[x*3 + c] = saturate_cast (v); } } } imshow("Spherize", dst); imwrite("Out.jpg", dst); waitKey(0); return 0; }
alpha (代碼中未直接使用,可擴展控制強度)K = PI/2:曲率常數,越小凸出越明顯。R:球面半徑,取短邊一半保證完整球面。