## 一、图像挤压特效

### 1、原理

图像上点P与图像中心O的距离为R，图像挤压就是P点坐标映射到OP直线上的点R2位置，其中| OR2 |=sqrt(OP)*ratio。

### 2、实现

void Pinch(Mat& img, Mat& dst, int degree)
{
if (degree < 1) degree = 1;
if (degree > 32) degree = 32;

if (dst.empty())
dst.create(img.rows, img.cols, img.type());
dst = cv::Scalar::all(0);

int chns = img.channels();
int height = img.rows;
int width = img.cols;

int midX = width / 2;
int midY = height / 2;
int i, j, k;
int X, Y, offsetX, offsetY;

for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
offsetX = j - midX;
offsetY = i - midY;

// 半径
radius = sqrtf((float)(offsetX*offsetX + offsetY * offsetY));

if (X < 0) X = 0;
if (X >= width) X = width - 1;
if (Y < 0) Y = 0;
if (Y >= height) Y = height - 1;

for (k = 0; k < chns; k++)
{
dst.at<Vec3b>(i, j)[k] = img.at<Vec3b>(Y, X)[k];
}
}
}
}

Mat src_img;
Mat dst_img;
int rato = 15;

void call_back(int, void*)
{
Pinch(src_img, dst_img, rato);
imshow("Pinch图", dst_img);
}

int main() {

imshow("原图", src_img);

Pinch(src_img, dst_img, rato);
imshow("Pinch图", dst_img);

namedWindow("Pinch图");
createTrackbar("Pinch倍率", "Pinch图", &rato, 50, call_back);
call_back(rato, 0);

waitKey(0);
}

## 二、哈哈镜特效

### 1、原理

图像坐标的非线性变换，实现k的根号与k的比值，sqrt(k)/k k1时总倍率为1，当k小于1时，总倍率为渐变倍率。

### 2、实现

void Pinch(Mat& img, Mat& dst, int x, int y, int degree)
{
if (dst.empty())
dst.create(img.rows, img.cols, img.type());

dst = cv::Scalar::all(0);
cout << "x,y " << x << " " << y << endl;

int chns = img.channels();
int height = img.rows;
int width = img.cols;

midX = x;
midY = y;
int R = 100;

int i, j, k;
int X, Y, offsetX, offsetY;

for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
offsetX = j - midX;
offsetY = i - midY;

// 半径
radius = sqrtf((float)(offsetX*offsetX + offsetY * offsetY));
X = (int)( cos(radian) * k) + midX;
Y = (int)( sin(radian) * k) +  midY;

if (X < 0) X = 0;
if (X >= width) X = width - 1;
if (Y < 0) Y = 0;
if (Y >= height) Y = height - 1;

for (k = 0; k < chns; k++)
{
dst.at<Vec3b>(i, j)[k] = img.at<Vec3b>(Y, X)[k];
}
}
else
{
for (k = 0; k < chns; k++)
{
dst.at<Vec3b>(i, j)[k] = img.at<Vec3b>(i, j)[k];
}
}
}
}

cout << " midX, midY " << midX << " " << midY << endl;
}

## 三、图像扭曲

for (int j = 0; j < width; j++)
{
double temp =  degree * sin(1.0 * j / width  *  pi * T ); // [-degree,degree]
temp = degree + temp;  // [0, 2*degree]
for (int i = int(temp + 0.5); i < height + temp - 2 * degree; i++)
{
X = (int)((i - temp) *  (height) / (height - degree));
if (X >= img.rows)
X = img.rows - 1;
if (X < 0)
X = 0;

for (int c = 0; c < chns; c++)
{
dst.at<Vec3b>(i, j)[c] = img.at<Vec3b>(X, j)[c];
}
}
}

## 4、参考文献

2、仿射变换

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html

3、PhotoShop算法实现高级篇--挤压特效（三十六）

https://blog.csdn.net/kezunhai/article/details/41873775

https://www.cnblogs.com/pingwen/p/12503047.html

posted on 2020-03-16 12:41  啊哈彭  阅读(...)  评论(...编辑  收藏