1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#include "opencv2/opencv.hpp"
#include <algorithm>
cv::Mat src_img;
cv::Mat lut_img;
int slider_intensity = 0;
int radius = 100;
bool leftdown = false;
cv::Point start = cv::Point(-1, -1);
cv::Point end = cv::Point(-1, -1);
cv::Point Liquefy(const cv::Point& c, const cv::Point& m, const cv::Point& x, const float r)
{
auto DistancePow = [](const cv::Point2f& p1, const cv::Point2f& p2){
return std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2);
};
cv::Point u = cv::Point(-1, -1);
cv::Point2f direction = m - c;
double factor = 0.2 * std::pow((r * r - DistancePow(x, c)) / (r * r - DistancePow(x, c) + DistancePow(m, c) ), 2);
u = x - cv::Point(factor * direction.x, factor * direction.y);
return u;
}
void Reshape(const cv::Mat& src, const cv::Point& start, const cv::Point& end, const float radius, cv::Mat& result)
{
if(src.empty()){ return;}
result = src.clone();
int rows = src.rows;
int cols = src.cols;
auto Distance = [](const cv::Point2f& p1, const cv::Point2f& p2){
return std::sqrt(std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2));
};
for(int r = 1; r < rows - 1; r++)
{
for(int c = 1; c < cols - 1; c++)
{
cv::Point2f p = cv::Point2f(c, r);
cv::Point2f rp = p;
if(Distance(p, start) < radius)
{
rp = Liquefy(start, end, p, radius);
}
result.at<cv::Vec3b>(p) = 0.4 * src.at<cv::Vec3b>(rp)
+ 0.15 * src.at<cv::Vec3b>(cv::Point2f(rp.x , rp.y -1) ) + 0.15 * src.at<cv::Vec3b>(cv::Point2f(rp.x -1, rp.y))
+ 0.15 * src.at<cv::Vec3b>(cv::Point2f(rp.x + 1, rp.y) )+ 0.15 * src.at<cv::Vec3b>(cv::Point2f(rp.x, rp.y + 1)) ;
}
}
}
void LutTrack(int, void*)
{
//无需处理
std::cout << "radius: "<< radius << std::endl;
}
void OnMouse(int event, int x, int y, int flag, void* usrdata)
{
if(event == cv::EVENT_LBUTTONDOWN)
{
start = cv::Point(x, y);
std::cout << "start: "<< x << "," << y << std::endl;
cv::Mat tmp = src_img.clone();
cv::circle(tmp, start, 2, cv::Scalar(0, 255, 0));
cv::circle(tmp, start, radius, cv::Scalar(0, 255, 0));
leftdown = true;
cv::imshow("liquefy", tmp);
}
if(flag == cv::EVENT_FLAG_LBUTTON)
{
cv::Point current = cv::Point(x,y);
std::cout << "current: "<< x << "," << y << std::endl;
cv::Mat tmp = src_img.clone();
cv::circle(tmp, start, 2, cv::Scalar(0, 255, 0));
cv::circle(tmp, start, radius, cv::Scalar(0, 255, 0));
cv::line(tmp, start, current, cv::Scalar(0, 255, 0));
cv::imshow("liquefy", tmp);
}
if(event == cv::EVENT_LBUTTONUP)
{
if(leftdown)
{
leftdown = false;
cv::Point end = cv::Point(x,y);
cv::Mat result;
Reshape(src_img, start, end, radius, result);
src_img = result;
cv::imshow("liquefy", result);
}
}
}
int main(int argc, char** argv)
{
src_img = cv::imread("/Volumes/HaoMingSSD/Learnning/effect/data/img/lut/1.jpg");
if(src_img.empty()) {return -1;}
cv::namedWindow("liquefy");
cv::setMouseCallback("liquefy", OnMouse, nullptr);
//cv::createTrackbar("radius", "liquefy", &radius, 100, LutTrack, nullptr);
//LutTrack(0, nullptr);
cv::imshow("liquefy", src_img);
cv::waitKey(0);
return 0;
}
|