Перейти к содержимому
Compvision.ru
Smorodov

Poisson Blender (бесшовная фрагментовставлялка)

Recommended Posts

Нашел на японском сайте и немного допилил реализацию Пуассоновой мешалки.

Если на входе:

post-1-0-07008600-1357485074_thumb.pngpost-1-0-46399700-1357485084_thumb.pngpost-1-0-86637000-1357485091_thumb.png

Вот что выдает:

post-1-0-61465000-1357485102_thumb.png

или, если поменять входные файлы местами:

post-1-0-86910900-1357485238_thumb.png

PoissonBlender.RAR

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

не понятен пример с одномерным случаем из этой лекции

 

откуда берутся формулы типа Min(f2-f1)^2, точнее понятно что мы потом минимизируем сумму квадратов производных, но как уравнение Лапласа сводиться к этому?

 

во втором варианте

 

тут пишут что лапласиан для одномерного случая это [1 -2 1] 

какая интерпретация того, что если в области градиент занулен, то ядро свертки [-1 2 -1](почему знак обратный?), если внутри градиент какой то есть, то [-2 4 -2]?

 

продолжение

http://eric-yuan.me/poisson-blending-2/

тут код почище и нет зависимости от eigen (использует solve из opencv), но может быть медленнее(?)

 

 

еще посмотрев исходный код в первом посте

 

при чём тут 0.125?

cv::Mat target_dx;
cv::Mat target_dy;


cv::Sobel(target64,target_dx,CV_64FC1,1,0,3,0.125);
cv::Sobel(target64,target_dy,CV_64FC1,0,1,3,0.125);

 

несколько методов решения discrete Poisson Equation 

www.cs.berkeley.edu/~demmel/cs267/lecture24/lecture24.html

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

посмотрев еще код по этой ссылке 

eric-yuan.me/poisson-blending-2/

выяснилось, что там не используется бинарная маска(а как же тогда задаются краевые условия?), а просто берется квадратная область и матрица А которая очень разрежена имеет размер

Mat A = Mat::eye(height * width, height * width, CV_64FC1);
Mat B = Mat::zeros(roiheight * roiwidth, 1, CV_64FC1);

, т.е. зависит от размера прямоугольной области.

 

и да opencv solve не умеет работать с разреженными матрицами. 

 

 

Решатели Sparse Linear Systems  

http://eigen.tuxfamily.org/dox-devel/group__TopicSparseSystems.html

 

 

В итоге тут неплохо описан процесс работы с маской:

https://github.com/gberger/COMP590/tree/master/A2

For pixels outside the masked region, the output pixel is simply equal to the destination matrix. For these, the corresponding row in the matrix A is the same as in the identity matrix, and the corresponding value in the vector b is simply the same pixel as the destination image.

However, for pixels inside the masked region, it gets a little more complicated. The output pixel depends on the neighbors. Specifically, we wish to satisfy the following equation:

4 * x(i,j) - x(i+1, j) - x(i-1, j) - x(i, j+1) - x(i, j-1) = b(i,j) = grad(src, i, j).

We express this equation by filling the appropriate cells in the coefficient matrix with 4 and -1, and the corresponding value in b with the gradient at the same pixel in the source image.

 

https://github.com/gberger/COMP590/blob/master/A2/src/poisson_blending.m

 

Тут более подробно описано как обращаться с краевыми пикселями:

http://www.ctralie.com/Teaching/PoissonImageEditing/

 

The linear equation is AX = b

X is all of the pixels you would like to solve for in the blended pasted image (I called this H...so each H(x, y) in your bounded region is an element of the X matrix....I know it gets confusing since x and y are also coordinates but capital X is a column matrix in this discussion that represents pixels in H). Each row of A is a constraint on a relationship between the pixels of H. If a pixel of H is completely in the interior of H and surrounded by 4 neighbors, then the constraint is simply that the gradient of a pixel of H is equal to the gradient of pixel B, similar to the equation you gave in a previous comment:

4H(x, y) - H(x+1, y) - H(x-1, y) - H(x, y+1) - H(x, y-1) = 4B(x, y) - B(x+1, y) - B(x-1, y) - B(x, y+1) - B(x, y-1)
The right hand side of that equation is computed beforehand and stored as an element in the "b" column matrix. The left hand side is what goes into the "A" matrix since it represents a relationship between the pixels that we need to solve for. So that row would probably look something like:
[0 0 0 ... 0 0 -1 -1 4 -1 -1 0 0 ... 0 0]
depending on how you ordered your pixels. This matrix is *very* sparse though, so you would probably not want to write the whole thing out in memory but instead to use a library like "CSparse" to solve this in C++http://www.cise.ufl.edu/resear...

So I explained the case for a pixel and its four neighbors on the interior of H. But if one of the neighbors of H(x, y) happens to be on the boundary of H, then its value is fixed because we want the boundary to match up with the pixels in image A. Let's say that the pixel at neighbor location (x-1, y) was on the boundary. Then the equation before would change to:
4H(x, y) - H(x+1, y) - A(x-1, y) - H(x, y+1) - H(x, y-1) = 4B(x, y) - B(x+1, y) - B(x-1, y) - B(x, y+1) - B(x, y-1)
since the values of the boundary are fixed and equal to the image we are pasting to. Since A(x-1, y) is a constant, move it to the right hand side of the equation
4H(x, y) - H(x+1, y) - H(x, y+1) - H(x, y-1) = 4B(x, y) - B(x+1, y) - B(x-1, y) - B(x, y+1) - B(x, y-1) + A(x-1, y)

If there aren't four valid neighbors (because of boundary constraints), for instance if neighbor (x, y+1) is out of bounds, then the equation will look like this:
3H(x, y) - H(x+1, y) - H(x, y-1) = 3B(x, y) - B(x+1, y) - B(x-1, y) - B(x, y-1) + A(x-1, y)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

в opencv 3.0 появилась ф-ия seamlessClone

 

пример

https://github.com/Itseez/opencv/blob/master/samples/cpp/cloning_demo.cpp

 

и еще много чего

    cout << "1) Normal Cloning " << endl;
    cout << "2) Mixed Cloning " << endl;
    cout << "3) Monochrome Transfer " << endl;
    cout << "4) Local Color Change " << endl;
    cout << "5) Local Illumination Change " << endl;
    cout << "6) Texture Flattening " << endl;

 

Но похоже там используется тот же solve для dense матриц

 

void Cloning::poissonSolver(const Mat &img, Mat &laplacianX , Mat &laplacianY, Mat &result)
{
    const int w = img.cols;
    const int h = img.rows;


    Mat lap = Mat(img.size(),CV_32FC1);


    lap = laplacianX + laplacianY;


    Mat bound = img.clone();


    rectangle(bound, Point(1, 1), Point(img.cols-2, img.rows-2), Scalar::all(0), -1);
    Mat boundary_points;
    Laplacian(bound, boundary_points, CV_32F);


    boundary_points = lap - boundary_points;


    Mat mod_diff = boundary_points(Rect(1, 1, w-2, h-2));


    solve(img,mod_diff,result);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×