├── .gitignore ├── LICENSE.md ├── README.md ├── command.txt ├── main.py ├── quilting.pdf ├── results ├── t1.png ├── t10.png ├── t11.png ├── t12.png ├── t13.png ├── t14.png ├── t15.png ├── t16.png ├── t17.png ├── t18.png ├── t19.png ├── t2.png ├── t20.png ├── t3.png ├── t4.png ├── t5.png ├── t6.png ├── t7.png ├── t8.png └── t9.png ├── textures ├── t1.png ├── t10.png ├── t11.png ├── t12.png ├── t13.png ├── t14.png ├── t15.png ├── t16.png ├── t17.png ├── t18.png ├── t19.png ├── t2.png ├── t20.png ├── t3.png ├── t4.png ├── t5.png ├── t6.png ├── t7.png ├── t8.png └── t9.png └── utils ├── __init__.py ├── __init__.pyc ├── generate.py ├── generate.pyc ├── preprocess.py └── preprocess.pyc /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Rohit Kumar Jena 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Image Quilting for Texture Synthesis 2 | 3 | This repository is an implementation of the image quilting algorithm for texture synthesis using Python. For more details on the algorithm, refer to the original paper by Alexei A. Efros and Willian T. Freeman [here](https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/papers/efros-siggraph01.pdf). 4 | 5 | ## Usage 6 | To run the code on a given texture, run the following code: 7 | 8 | `python main.py --image_path --block_size --overlap --scale --num_outputs --output_file --plot --tolerance ` 9 | 10 | For more details, use `python main.py -h` 11 | 12 | ## Results 13 | Here are some results of the image quilting for texture synthesis algorithm. 14 | 15 | 16 | ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/textures/t16.png) ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/results/t16.png) 17 | 18 | ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/textures/t6.png) ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/results/t6.png) 19 | 20 | 21 | ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/textures/t12.png) ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/results/t12.png) 22 | 23 | ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/textures/t14.png) ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/results/t14.png) 24 | 25 | ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/textures/t18.png) ![](https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/master/results/t18.png) 26 | 27 | ## References 28 | This is the main paper.
29 |
30 | 31 | Image Quilting for Texture Synthesis and Transfer Proceedings of SIGGRAPH 2001 (August 2001), pp. 341-346 by Alexei A. Efros, William T. Freeman edited by Eugene Fiume 32 |
-------------------------------------------------------------------------------- /command.txt: -------------------------------------------------------------------------------- 1 | for i in {1..20..1}; do python main.py -i textures/t20.png -s 2 -b 60 -p 0 -f results/t20.png; done 2 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | import argparse 4 | import cv2 5 | from matplotlib import pyplot as plt 6 | from utils.preprocess import * 7 | from utils.generate import * 8 | from math import ceil 9 | 10 | ## Get parser arguments 11 | parser = argparse.ArgumentParser() 12 | parser.add_argument("-i", "--image_path", required=True, type=str, help="path of image you want to quilt") 13 | parser.add_argument("-b", "--block_size", type=int, default=20, help="block size in pixels") 14 | parser.add_argument("-o", "--overlap", type=int, default=1.0/6, help="overlap size in pixels (defaults to 1/6th of block size)") 15 | parser.add_argument("-s", "--scale", type=float, default=4, help="Scaling w.r.t. to image size") 16 | parser.add_argument("-n", "--num_outputs", type=int, default=1, help="number of output textures required") 17 | parser.add_argument("-f", "--output_file", type=str, default="output.png", help="output file name") 18 | parser.add_argument("-p", "--plot", type=int, default=1, help="Show plots") 19 | parser.add_argument("-t", "--tolerance", type=float, default=0.1, help="Tolerance fraction") 20 | 21 | args = parser.parse_args() 22 | 23 | if __name__ == "__main__": 24 | # Start the main loop here 25 | path = args.image_path 26 | block_size = args.block_size 27 | scale = args.scale 28 | overlap = args.overlap 29 | print("Using plot {}".format(args.plot)) 30 | # Set overlap to 1/6th of block size 31 | if overlap > 0: 32 | overlap = int(block_size*args.overlap) 33 | else: 34 | overlap = int(block_size/6.0) 35 | 36 | # Get all blocks 37 | image = cv2.imread(path) 38 | image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)/255.0 39 | print("Image size: ({}, {})".format(*image.shape[:2])) 40 | 41 | H, W = image.shape[:2] 42 | outH, outW = int(scale*H), int(scale*W) 43 | 44 | for i in range(args.num_outputs): 45 | textureMap = generateTextureMap(image, block_size, overlap, outH, outW, args.tolerance) 46 | if args.plot: 47 | plt.imshow(textureMap) 48 | plt.show() 49 | 50 | # Save 51 | textureMap = (255*textureMap).astype(np.uint8) 52 | textureMap = cv2.cvtColor(textureMap, cv2.COLOR_RGB2BGR) 53 | if args.num_outputs == 1: 54 | cv2.imwrite(args.output_file, textureMap) 55 | print("Saved output to {}".format(args.output_file)) 56 | else: 57 | cv2.imwrite(args.output_file.replace(".", "_{}.".format(i)), textureMap) 58 | print("Saved output to {}".format(args.output_file.replace(".", "_{}.".format(i)))) -------------------------------------------------------------------------------- /quilting.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/quilting.pdf -------------------------------------------------------------------------------- /results/t1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t1.png -------------------------------------------------------------------------------- /results/t10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t10.png -------------------------------------------------------------------------------- /results/t11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t11.png -------------------------------------------------------------------------------- /results/t12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t12.png -------------------------------------------------------------------------------- /results/t13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t13.png -------------------------------------------------------------------------------- /results/t14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t14.png -------------------------------------------------------------------------------- /results/t15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t15.png -------------------------------------------------------------------------------- /results/t16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t16.png -------------------------------------------------------------------------------- /results/t17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t17.png -------------------------------------------------------------------------------- /results/t18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t18.png -------------------------------------------------------------------------------- /results/t19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t19.png -------------------------------------------------------------------------------- /results/t2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t2.png -------------------------------------------------------------------------------- /results/t20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t20.png -------------------------------------------------------------------------------- /results/t3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t3.png -------------------------------------------------------------------------------- /results/t4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t4.png -------------------------------------------------------------------------------- /results/t5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t5.png -------------------------------------------------------------------------------- /results/t6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t6.png -------------------------------------------------------------------------------- /results/t7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t7.png -------------------------------------------------------------------------------- /results/t8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t8.png -------------------------------------------------------------------------------- /results/t9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/results/t9.png -------------------------------------------------------------------------------- /textures/t1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t1.png -------------------------------------------------------------------------------- /textures/t10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t10.png -------------------------------------------------------------------------------- /textures/t11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t11.png -------------------------------------------------------------------------------- /textures/t12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t12.png -------------------------------------------------------------------------------- /textures/t13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t13.png -------------------------------------------------------------------------------- /textures/t14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t14.png -------------------------------------------------------------------------------- /textures/t15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t15.png -------------------------------------------------------------------------------- /textures/t16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t16.png -------------------------------------------------------------------------------- /textures/t17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t17.png -------------------------------------------------------------------------------- /textures/t18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t18.png -------------------------------------------------------------------------------- /textures/t19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t19.png -------------------------------------------------------------------------------- /textures/t2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t2.png -------------------------------------------------------------------------------- /textures/t20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t20.png -------------------------------------------------------------------------------- /textures/t3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t3.png -------------------------------------------------------------------------------- /textures/t4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t4.png -------------------------------------------------------------------------------- /textures/t5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t5.png -------------------------------------------------------------------------------- /textures/t6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t6.png -------------------------------------------------------------------------------- /textures/t7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t7.png -------------------------------------------------------------------------------- /textures/t8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t8.png -------------------------------------------------------------------------------- /textures/t9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/textures/t9.png -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/utils/__init__.py -------------------------------------------------------------------------------- /utils/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/utils/__init__.pyc -------------------------------------------------------------------------------- /utils/generate.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | import cv2 4 | from matplotlib import pyplot as plt 5 | from math import ceil 6 | from itertools import product 7 | 8 | inf = np.float('inf') 9 | ErrorCombinationFunc = np.add 10 | 11 | 12 | def findPatchHorizontal(refBlock, texture, blocksize, overlap, tolerance): 13 | ''' 14 | Find best horizontal match from the texture 15 | ''' 16 | H, W = texture.shape[:2] 17 | errMat = np.zeros((H-blocksize, W-blocksize)) + inf 18 | for i, j in product(range(H-blocksize), range(W-blocksize)): 19 | rmsVal = ((texture[i:i+blocksize, j:j+overlap] - refBlock[:, -overlap:])**2).mean() 20 | if rmsVal > 0: 21 | errMat[i, j] = rmsVal 22 | 23 | minVal = np.min(errMat) 24 | y, x = np.where(errMat < (1.0 + tolerance)*(minVal)) 25 | c = np.random.randint(len(y)) 26 | y, x = y[c], x[c] 27 | return texture[y:y+blocksize, x:x+blocksize] 28 | 29 | 30 | def findPatchBoth(refBlockLeft, refBlockTop, texture, blocksize, overlap, tolerance): 31 | ''' 32 | Find best horizontal and vertical match from the texture 33 | ''' 34 | H, W = texture.shape[:2] 35 | errMat = np.zeros((H-blocksize, W-blocksize)) + inf 36 | for i, j in product(range(H-blocksize), range(W-blocksize)): 37 | rmsVal = ((texture[i:i+overlap, j:j+blocksize] - refBlockTop[-overlap:, :])**2).mean() 38 | rmsVal = rmsVal + ((texture[i:i+blocksize, j:j+overlap] - refBlockLeft[:, -overlap:])**2).mean() 39 | if rmsVal > 0: 40 | errMat[i, j] = rmsVal 41 | 42 | minVal = np.min(errMat) 43 | y, x = np.where(errMat < (1.0 + tolerance)*(minVal)) 44 | c = np.random.randint(len(y)) 45 | y, x = y[c], x[c] 46 | return texture[y:y+blocksize, x:x+blocksize] 47 | 48 | 49 | def findPatchVertical(refBlock, texture, blocksize, overlap, tolerance): 50 | ''' 51 | Find best vertical match from the texture 52 | ''' 53 | H, W = texture.shape[:2] 54 | errMat = np.zeros((H-blocksize, W-blocksize)) + inf 55 | for i, j in product(range(H-blocksize), range(W-blocksize)): 56 | rmsVal = ((texture[i:i+overlap, j:j+blocksize] - refBlock[-overlap:, :])**2).mean() 57 | if rmsVal > 0: 58 | errMat[i, j] = rmsVal 59 | 60 | minVal = np.min(errMat) 61 | y, x = np.where(errMat < (1.0 + tolerance)*(minVal)) 62 | c = np.random.randint(len(y)) 63 | y, x = y[c], x[c] 64 | return texture[y:y+blocksize, x:x+blocksize] 65 | 66 | 67 | def getMinCutPatchHorizontal(block1, block2, blocksize, overlap): 68 | ''' 69 | Get the min cut patch done horizontally 70 | ''' 71 | err = ((block1[:, -overlap:] - block2[:, :overlap])**2).mean(2) 72 | # maintain minIndex for 2nd row onwards and 73 | minIndex = [] 74 | E = [list(err[0])] 75 | for i in range(1, err.shape[0]): 76 | # Get min values and args, -1 = left, 0 = middle, 1 = right 77 | e = [inf] + E[-1] + [inf] 78 | e = np.array([e[:-2], e[1:-1], e[2:]]) 79 | # Get minIndex 80 | minArr = e.min(0) 81 | minArg = e.argmin(0) - 1 82 | minIndex.append(minArg) 83 | # Set Eij = e_ij + min_ 84 | Eij = err[i] + minArr 85 | E.append(list(Eij)) 86 | 87 | # Check the last element and backtrack to find path 88 | path = [] 89 | minArg = np.argmin(E[-1]) 90 | path.append(minArg) 91 | 92 | # Backtrack to min path 93 | for idx in minIndex[::-1]: 94 | minArg = minArg + idx[minArg] 95 | path.append(minArg) 96 | # Reverse to find full path 97 | path = path[::-1] 98 | mask = np.zeros((blocksize, blocksize, block1.shape[2])) 99 | for i in range(len(path)): 100 | mask[i, :path[i]+1] = 1 101 | 102 | resBlock = np.zeros(block1.shape) 103 | resBlock[:, :overlap] = block1[:, -overlap:] 104 | resBlock = resBlock*mask + block2*(1-mask) 105 | # resBlock = block1*mask + block2*(1-mask) 106 | return resBlock 107 | 108 | 109 | def getMinCutPatchVertical(block1, block2, blocksize, overlap): 110 | ''' 111 | Get the min cut patch done vertically 112 | ''' 113 | resBlock = getMinCutPatchHorizontal(np.rot90(block1), np.rot90(block2), blocksize, overlap) 114 | return np.rot90(resBlock, 3) 115 | 116 | 117 | def getMinCutPatchBoth(refBlockLeft, refBlockTop, patchBlock, blocksize, overlap): 118 | ''' 119 | Find minCut for both and calculate 120 | ''' 121 | err = ((refBlockLeft[:, -overlap:] - patchBlock[:, :overlap])**2).mean(2) 122 | # maintain minIndex for 2nd row onwards and 123 | minIndex = [] 124 | E = [list(err[0])] 125 | for i in range(1, err.shape[0]): 126 | # Get min values and args, -1 = left, 0 = middle, 1 = right 127 | e = [inf] + E[-1] + [inf] 128 | e = np.array([e[:-2], e[1:-1], e[2:]]) 129 | # Get minIndex 130 | minArr = e.min(0) 131 | minArg = e.argmin(0) - 1 132 | minIndex.append(minArg) 133 | # Set Eij = e_ij + min_ 134 | Eij = err[i] + minArr 135 | E.append(list(Eij)) 136 | 137 | # Check the last element and backtrack to find path 138 | path = [] 139 | minArg = np.argmin(E[-1]) 140 | path.append(minArg) 141 | 142 | # Backtrack to min path 143 | for idx in minIndex[::-1]: 144 | minArg = minArg + idx[minArg] 145 | path.append(minArg) 146 | # Reverse to find full path 147 | path = path[::-1] 148 | mask1 = np.zeros((blocksize, blocksize, patchBlock.shape[2])) 149 | for i in range(len(path)): 150 | mask1[i, :path[i]+1] = 1 151 | 152 | ################################################################### 153 | ## Now for vertical one 154 | err = ((np.rot90(refBlockTop)[:, -overlap:] - np.rot90(patchBlock)[:, :overlap])**2).mean(2) 155 | # maintain minIndex for 2nd row onwards and 156 | minIndex = [] 157 | E = [list(err[0])] 158 | for i in range(1, err.shape[0]): 159 | # Get min values and args, -1 = left, 0 = middle, 1 = right 160 | e = [inf] + E[-1] + [inf] 161 | e = np.array([e[:-2], e[1:-1], e[2:]]) 162 | # Get minIndex 163 | minArr = e.min(0) 164 | minArg = e.argmin(0) - 1 165 | minIndex.append(minArg) 166 | # Set Eij = e_ij + min_ 167 | Eij = err[i] + minArr 168 | E.append(list(Eij)) 169 | 170 | # Check the last element and backtrack to find path 171 | path = [] 172 | minArg = np.argmin(E[-1]) 173 | path.append(minArg) 174 | 175 | # Backtrack to min path 176 | for idx in minIndex[::-1]: 177 | minArg = minArg + idx[minArg] 178 | path.append(minArg) 179 | # Reverse to find full path 180 | path = path[::-1] 181 | mask2 = np.zeros((blocksize, blocksize, patchBlock.shape[2])) 182 | for i in range(len(path)): 183 | mask2[i, :path[i]+1] = 1 184 | mask2 = np.rot90(mask2, 3) 185 | 186 | 187 | mask2[:overlap, :overlap] = np.maximum(mask2[:overlap, :overlap] - mask1[:overlap, :overlap], 0) 188 | 189 | # Put first mask 190 | resBlock = np.zeros(patchBlock.shape) 191 | resBlock[:, :overlap] = mask1[:, :overlap]*refBlockLeft[:, -overlap:] 192 | resBlock[:overlap, :] = resBlock[:overlap, :] + mask2[:overlap, :]*refBlockTop[-overlap:, :] 193 | resBlock = resBlock + (1-np.maximum(mask1, mask2))*patchBlock 194 | return resBlock 195 | 196 | 197 | 198 | 199 | def generateTextureMap(image, blocksize, overlap, outH, outW, tolerance): 200 | nH = int(ceil((outH - blocksize)*1.0/(blocksize - overlap))) 201 | nW = int(ceil((outW - blocksize)*1.0/(blocksize - overlap))) 202 | 203 | textureMap = np.zeros(((blocksize + nH*(blocksize - overlap)), (blocksize + nW*(blocksize - overlap)), image.shape[2])) 204 | 205 | # Starting index and block 206 | H, W = image.shape[:2] 207 | randH = np.random.randint(H - blocksize) 208 | randW = np.random.randint(W - blocksize) 209 | 210 | startBlock = image[randH:randH+blocksize, randW:randW+blocksize] 211 | textureMap[:blocksize, :blocksize, :] = startBlock 212 | 213 | # Fill the first row 214 | for i, blkIdx in enumerate(range((blocksize-overlap), textureMap.shape[1]-overlap, (blocksize-overlap))): 215 | # Find horizontal error for this block 216 | # Calculate min, find index having tolerance 217 | # Choose one randomly among them 218 | # blkIdx = block index to put in 219 | refBlock = textureMap[:blocksize, (blkIdx-blocksize+overlap):(blkIdx+overlap)] 220 | patchBlock = findPatchHorizontal(refBlock, image, blocksize, overlap, tolerance) 221 | minCutPatch = getMinCutPatchHorizontal(refBlock, patchBlock, blocksize, overlap) 222 | textureMap[:blocksize, (blkIdx):(blkIdx+blocksize)] = minCutPatch 223 | print("{} out of {} rows complete...".format(1, nH+1)) 224 | 225 | 226 | ### Fill the first column 227 | for i, blkIdx in enumerate(range((blocksize-overlap), textureMap.shape[0]-overlap, (blocksize-overlap))): 228 | # Find vertical error for this block 229 | # Calculate min, find index having tolerance 230 | # Choose one randomly among them 231 | # blkIdx = block index to put in 232 | refBlock = textureMap[(blkIdx-blocksize+overlap):(blkIdx+overlap), :blocksize] 233 | patchBlock = findPatchVertical(refBlock, image, blocksize, overlap, tolerance) 234 | minCutPatch = getMinCutPatchVertical(refBlock, patchBlock, blocksize, overlap) 235 | 236 | textureMap[(blkIdx):(blkIdx+blocksize), :blocksize] = minCutPatch 237 | 238 | ### Fill in the other rows and columns 239 | for i in range(1, nH+1): 240 | for j in range(1, nW+1): 241 | # Choose the starting index for the texture placement 242 | blkIndexI = i*(blocksize-overlap) 243 | blkIndexJ = j*(blocksize-overlap) 244 | # Find the left and top block, and the min errors independently 245 | refBlockLeft = textureMap[(blkIndexI):(blkIndexI+blocksize), (blkIndexJ-blocksize+overlap):(blkIndexJ+overlap)] 246 | refBlockTop = textureMap[(blkIndexI-blocksize+overlap):(blkIndexI+overlap), (blkIndexJ):(blkIndexJ+blocksize)] 247 | 248 | patchBlock = findPatchBoth(refBlockLeft, refBlockTop, image, blocksize, overlap, tolerance) 249 | minCutPatch = getMinCutPatchBoth(refBlockLeft, refBlockTop, patchBlock, blocksize, overlap) 250 | 251 | textureMap[(blkIndexI):(blkIndexI+blocksize), (blkIndexJ):(blkIndexJ+blocksize)] = minCutPatch 252 | 253 | # refBlockLeft = 0.5 254 | # textureMap[(blkIndexI):(blkIndexI+blocksize), (blkIndexJ-blocksize+overlap):(blkIndexJ+overlap)] = refBlockLeft 255 | # textureMap[(blkIndexI-blocksize+overlap):(blkIndexI+overlap), (blkIndexJ):(blkIndexJ+blocksize)] = [0.5, 0.6, 0.7] 256 | # break 257 | print("{} out of {} rows complete...".format(i+1, nH+1)) 258 | # break 259 | 260 | return textureMap 261 | -------------------------------------------------------------------------------- /utils/generate.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/utils/generate.pyc -------------------------------------------------------------------------------- /utils/preprocess.py: -------------------------------------------------------------------------------- 1 | ## Handles all the preprocessing 2 | import numpy as np 3 | from itertools import product 4 | from matplotlib import pyplot as plt 5 | 6 | inf = np.float('inf') 7 | 8 | def rasterScan(image, blocksize, step=None): 9 | ''' 10 | Perform raster scan for image with squared block size "b" 11 | - If block size is not divisible by image size, then take all except last block 12 | - And for the last block, take the block from the other end 13 | ''' 14 | block_list = [] 15 | if step is None: 16 | step = blocksize 17 | 18 | H, W = image.shape[:2] 19 | Y = range(0, H-blocksize, step) 20 | X = range(0, W-blocksize, step) 21 | if H%step != 0: 22 | Y = Y[:-1] 23 | if W%step != 0: 24 | X = X[:-1] 25 | 26 | for y in Y: 27 | for x in X: 28 | block_list.append(image[y:y+blocksize, x:x+blocksize, :]) 29 | 30 | print("Created {} blocks.".format(len(block_list))) 31 | return block_list 32 | 33 | def VerticalOverlap(im1, im2, blocksize, overlap): 34 | ''' 35 | Horizontal overlap between im1 (left) and im2 (right) 36 | ''' 37 | im1Rot = np.rot90(im1) 38 | im2Rot = np.rot90(im2) 39 | 40 | mask, minVal = HorizontalOverlap(im1Rot, im2Rot, blocksize, overlap) 41 | mask = np.rot90(mask, 3) 42 | 43 | # plt.imshow(mask) 44 | # plt.show() 45 | return mask, minVal 46 | -------------------------------------------------------------------------------- /utils/preprocess.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rohitrango/Image-Quilting-for-Texture-Synthesis/2404367110956323430613407495396da3eb1c0c/utils/preprocess.pyc --------------------------------------------------------------------------------