Before I sent a number of series blog carefully study the Poisson Image editing algorithm, each time re-examination and depth, as if all can have a deeper understanding and great harvest. This should be the end of my series, will use the MATLAB code 1.1 point of the demonstration, the original author is how to design and implement his powerful and far-reaching algorithm. I hope you look at this article before you must refer to the article to understand the principle of the algorithm, this article will mainly explain the implementation of the problem of programming, for the above mentioned content, I will not delve into. But my personal overall feeling is that now the image processing algorithm to the mathematical requirements are more and more high, such as Poisson Fusion, Poisson cutout algorithm if there is no partial differential equation (this algorithm involves Poisson equation), numerical calculation (need Gaussian-Sidell iterative method or conjugate gradient method), Field theory (involving divergence, gradient and Laplace operators ), matrix theory (involving large sparse matrix systems of linear equations), mathematical physics methods (involving elliptic curve equations with Dirichlet conditions), optimization theory (involving Euler-Langrages variational method) These difficult mathematical knowledge, It is too difficult to understand (every step is a hurdle, I feel that there is a place, the essence of the classic paper can not be grasped, let alone the implementation of programming).
image processing Let the palms grow eyes, in fact, the mouth can also ~image Poisson (Poisson) editing, Poisson Fusion fully detailed (3) image Poisson (Poisson) editing, Poisson fusion fully detailed (2) image Poisson (Poisson) editing, Poisson fusion fully detailed (1)
The material is three pictures, as follows
bear.jpg Bear-mask.jpg
Pool-target.jpg
First, let's clean up the MATLAB environment:
Close ALL;CLEAR;CLC;
then, read three images (note that the mask is read in the form of a two-value graph)
Targetimg = imread (' pool-target.jpg '); Sourceimg = imread (' bear.jpg '); SourceMask = IM2BW (Imread (' bear-mask.jpg '));
Using the function bwboundaries (w,conn) to obtain the contour of the object in the binary graph, where the CONN is 8 or 4, indicating that the connectivity uses 4-direction neighbor Point discriminant or 8-direction neighborhood point discriminant, the default is 8.
[Srcboundry, ~] = bwboundaries (SourceMask, 8);
Then we draw this contour on the sourceimg to show the area we are going to cut. The parameter ' R ' indicates red.
Figure, Imshow (sourceimg), axis imagehold onfor k = 1:length (srcboundry) boundary = srcboundry{k}; Plot (Boundary (:, 2), Boundary (:, 1), ' R ', ' LineWidth ', 2) endtitle (' Source image intended area for cutting from ');
The results obtained are as follows
Sets the location where the source will be pasted in the target map and gets the length and width of the targetimg.
Position_in_target = [Ten, 225];%xy[targetrows, Targetcols, ~] = size (targetimg);
function Find () functions: B=find (x), X is a matrix, query the position of a non-0 element, if X is a row vector, returns a row vector, otherwise, returns a column vector.
[Row, col] = find (SourceMask);
then, calculate the size of the mask box in the source graph.
Start_pos = [min (col), Min (row)];end_pos = [Max (col), Max (row)];frame_size = End_pos-start_pos;
if placing the frame in the position_in_target position will exceed the range of the target graph, change the position_in_target to ensure that the frame does not exceed the range of the target map.
if (frame_size (1) + position_in_target (1) > Targetcols) position_in_target (1) = Targetcols-frame_size (1); endif (Frame_size (2) + position_in_target (2) > Targetrows) Position_in_target (2) = Targetrows-frame_size (2); end
Build a new mask that is equal to the target graph, and then place the SourceMask in the position_in_target position.
Masktarget = Zeros (targetrows, targetcols); Masktarget (Sub2ind ([Targetrows, Targetcols], Row-start_pos (2) + position_in_target (2), ... col-start_pos (1) + position _in_target (1))) = 1;
at this point we get the new Masktarget as shown
As before, get the outline of the object in the binary image and draw the outline on the targetimg.
Targboundry = Bwboundaries (Masktarget, 8); figure, Imshow (targetimg), axis imagehold onfor k = 1:length (targboundry) boundary = targboundry{k}; Plot (Boundary (:, 2), Boundary (:, 1), ' R ', ' LineWidth ', 1) endtitle (' Target Image with intended place for pasting Source ');
The result is as shown
According to the algorithm given in the article we know that for the inside of the mask contour, we do not consider the boundary term, when the calculation gradient (G) of the divergence Div, is to execute a Laplace operator, as follows
Div (G (Source (x, y)))
=-4 F (x, Y) + f (x-1,y) + f (x,y-1) + f (x+1,y) + f (x,y+1) The Laplace operator is executed on the sourceimg, then the R, G, and b three components of the result are extracted.
TEMPLT = [0-1 0;-1 4-1; 0-1 0]; Laplaciansource = IMFilter (double (sourceimg), TEMPLT, ' replicate '); VR = Laplaciansource (:,:, 1); VG = Laplaciansource (:,:, 2); VB = Laplaciansource (:,:, 3);
Then, according to mask, the above calculation results are pasted into targetimg.
Targetimgr = Double (Targetimg (:,:, 1)); TARGETIMGG = Double (Targetimg (:,:, 2)); TARGETIMGB = Double (Targetimg (:,:, 3)); Targetimgr (Logical (Masktarget (:))) = VR (SourceMask (:)); TARGETIMGG (Logical (Masktarget (:))) = VG (SourceMask (:)); TARGETIMGB (Logical (Masktarget (:))) = VB (SourceMask (:)); Targetimgnew = Cat (3, Targetimgr, TARGETIMGG, TARGETIMGB), figure, Imagesc (Uint8 (targetimgnew)), axis image, title (' Target image with Laplacian of source inserted ');
The result is as shown
Then, we are going to calculate the sparse pro-connect matrix. (This place needs to refer to the previously given blog post 1)
If you simply parse from code, suppose we now have a mask
Mask = 0 0 0 0 0 0 1 (1) 1 (2) 0 0 0 1 (3) 1 (4) 1 (5) 0 0 0 1 (6) 1 (7) 0 0 0 0 0 0
So we're going to create a 7x7 adjacency matrix, for example (1) is (2) adjacency, so the position of [[] and [2,1] in the matrix below is 1.
>> neighbors = calcadjancency (mask);>> full (neighbors) ans = 0 1 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 1 0
Here we give the implementation code for the function calcadjancency ():
function neighbors = calcadjancency (mask) [height, Width] = size (mask); [ Row_mask, Col_mask] = find (mask), neighbors = sparse (Length (row_mask), Length (Row_mask), 0),% subscript goto Index ROI_IDXS = Sub2ind ([ Height, Width], row_mask, col_mask); for k = 1:size (Row_mask, 1), %4 adjacency point connected_4 = [Row_mask (k), Col_mask (k)-1 ;%left Row_mask (k), Col_mask (k) +1;%right Row_mask (k)-1, Col_mask (k);%top Row_mask (k) +1, Col_mask (k)]; %bottom ind_neighbors = Sub2ind ([height, width], connected_4 (:, 1), Connected_4 (:, 2)); % binary Lookup Function i = ISMEMBC2 (t, X): Returns the position of T in X, where x must be an incrementing numerical vector for neighbor_idx = 1:4,%number of neighbors, Adjacent_pixel _idx = ISMEMBC2 (ind_neighbors (NEIGHBOR_IDX), ROI_IDXS); if (adjacent_pixel_idx ~= 0) Neighbors (k, adjacent_pixel_idx) = 1; End End EndEnd
The first thing you should know in the above code is the binary lookup function ISMEMBC2 () of Matlab, which my comments are quite clear and no longer discussed. Another place is the subscript to index function sub2ind (). The following example illustrates its usage and significance:
% e.g. M =%% ( 1) (5) 14% (6) 24% ( 7) 34% 42 44% roi_idxs = sub2ind (Size (M), [1, 1, 2, 3], [2, 1, 2, 2])% ROI_IDXS =%% 5 1 6 7
returning to our skeleton program, we call the function calcadjancency () to calculate the adjacency matrix of the Ω region in Masktarget.
Adjacencymat = Calcadjancency (masktarget);
We then call the Poissonsolver () function to solve the linear equations for the R, G, and b three components of a color image respectively. The core is to use iterative method to solve large-scale sparse linear equations such as ax=b. Patrick Perez used the Gaussian-Sidell iterative method in the original text. Similarly, it may be more convenient to call the Conjugate gradient method function in MATLAB directly to solve it. Refer to the Help information given in MATLAB as follows:
x = CGS (A, B) attempts to solve the system of linear equations a*x=b for X.
The n*n coefficient matrix A must is square and the right hand side column vector B must has length N.
Resultimgr = Poissonsolver (Targetimgr, Masktarget, Adjacencymat, Targboundry); RESULTIMGG = Poissonsolver (Targetimgg, Masktarget, Adjacencymat, Targboundry); RESULTIMGB = Poissonsolver (TARGETIMGB, Masktarget, Adjacencymat, Targboundry);
finally we combine the three components and show the final fusion results.
Resultimg = Cat (3, Resultimgr, RESULTIMGG, RESULTIMGB); Figure;imshow (Uint8 (resultimg));
as shown in the following:
More examples and discussions
Establishing a sparse matrix in MATLAB If you simply use the zeros () or ones () function, when the picture is a little larger (for example, the diagram I used to do the following hand-eye fusion example), the issue of out of memory is generated. Therefore, the program should pay special attention to the use of sparse () and so on to establish a sparse matrix function to avoid hyper-memory problems.
Complete the full text.
If you're an image-processing channel, Welcome to the image Processing Learning Group (529549320).
Poisson image editing algorithm for MATLAB code parsing