Spaces:
Running
Running
new modes added, fixes in old methods and improvements in the server
Browse files- .DS_Store +0 -0
- recolorLinearColorTransfer.py +43 -19
- recolorPaletteBasedTransfer.py +7 -2
- recolorReinhardV2Algo.py +40 -7
- server.py +13 -0
- todo.md +3 -7
.DS_Store
CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
|
|
recolorLinearColorTransfer.py
CHANGED
@@ -5,35 +5,36 @@
|
|
5 |
#based on this: https://github.com/ProGamerGov/Neural-Tools
|
6 |
|
7 |
import numpy as np
|
8 |
-
import argparse
|
9 |
import imageio
|
10 |
from skimage import io,transform,img_as_float
|
11 |
from skimage.io import imread,imsave
|
12 |
from PIL import Image
|
13 |
-
from numpy import eye
|
|
|
14 |
|
15 |
-
parser = argparse.ArgumentParser()
|
16 |
-
parser.add_argument('-t', '--target_image', type=str, help="The image you are transfering color to. Ex: target.png", required=True)
|
17 |
-
parser.add_argument('-s', '--source_image', type=str, help="The image you are transfering color from. Ex: source.png", required=True)
|
18 |
-
parser.add_argument('-o', '--output_image', default='output.png', help="The name of your output image. Ex: output.png", type=str)
|
19 |
-
parser.add_argument('-m', '--mode', default='pca', help="The color transfer mode. Options are pca, chol, or sym.", type=str)
|
20 |
-
parser.add_argument('-e', '--eps', default='1e-5', help="Your epsilon value in scientific notation or normal notation. Ex: 1e-5 or 0.00001", type=float)
|
21 |
-
parser.parse_args()
|
22 |
-
args = parser.parse_args()
|
23 |
|
24 |
|
25 |
Image.MAX_IMAGE_PIXELS = 1000000000 # Support gigapixel images
|
26 |
|
27 |
|
28 |
-
def main():
|
29 |
|
30 |
-
|
31 |
-
|
32 |
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
|
38 |
|
39 |
def match_color(target_img, source_img, mode='pca', eps=1e-5):
|
@@ -75,5 +76,28 @@ def match_color(target_img, source_img, mode='pca', eps=1e-5):
|
|
75 |
return matched_img
|
76 |
|
77 |
|
78 |
-
if __name__ == "__main__":
|
79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
#based on this: https://github.com/ProGamerGov/Neural-Tools
|
6 |
|
7 |
import numpy as np
|
8 |
+
# import argparse
|
9 |
import imageio
|
10 |
from skimage import io,transform,img_as_float
|
11 |
from skimage.io import imread,imsave
|
12 |
from PIL import Image
|
13 |
+
from numpy import eye
|
14 |
+
import cv2
|
15 |
|
16 |
+
# parser = argparse.ArgumentParser()
|
17 |
+
# parser.add_argument('-t', '--target_image', type=str, help="The image you are transfering color to. Ex: target.png", required=True)
|
18 |
+
# parser.add_argument('-s', '--source_image', type=str, help="The image you are transfering color from. Ex: source.png", required=True)
|
19 |
+
# parser.add_argument('-o', '--output_image', default='output.png', help="The name of your output image. Ex: output.png", type=str)
|
20 |
+
# parser.add_argument('-m', '--mode', default='pca', help="The color transfer mode. Options are pca, chol, or sym.", type=str)
|
21 |
+
# parser.add_argument('-e', '--eps', default='1e-5', help="Your epsilon value in scientific notation or normal notation. Ex: 1e-5 or 0.00001", type=float)
|
22 |
+
# parser.parse_args()
|
23 |
+
# args = parser.parse_args()
|
24 |
|
25 |
|
26 |
Image.MAX_IMAGE_PIXELS = 1000000000 # Support gigapixel images
|
27 |
|
28 |
|
29 |
+
# def main():
|
30 |
|
31 |
+
# target_img = imageio.v2.imread(args.target_image, pilmode="RGB").astype(float)/256
|
32 |
+
# source_img = imageio.v2.imread(args.source_image, pilmode="RGB").astype(float)/256
|
33 |
|
34 |
+
# output_img = match_color(target_img, source_img, mode=args.mode, eps=args.eps)
|
35 |
+
# output_img = (output_img * 255).astype(np.uint8)
|
36 |
+
# imsave(args.output_image, output_img)
|
37 |
+
# # imsave(args.output_image, output_img)
|
38 |
|
39 |
|
40 |
def match_color(target_img, source_img, mode='pca', eps=1e-5):
|
|
|
76 |
return matched_img
|
77 |
|
78 |
|
79 |
+
# if __name__ == "__main__":
|
80 |
+
# main()
|
81 |
+
|
82 |
+
def create_target_image(hex_colors):
|
83 |
+
# Convert hex colors to RGB
|
84 |
+
rgb_colors = [tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) for hex_color in hex_colors]
|
85 |
+
|
86 |
+
# Create an image with the RGB colors
|
87 |
+
target_image = np.zeros((100, len(rgb_colors), 3), dtype=np.uint8)
|
88 |
+
for i, rgb_color in enumerate(rgb_colors):
|
89 |
+
target_image[:, i] = rgb_color
|
90 |
+
|
91 |
+
return target_image
|
92 |
+
|
93 |
+
def recolor(image_np, colors):
|
94 |
+
colors = [color.replace('#', '') for color in colors]
|
95 |
+
palette = create_target_image(colors)
|
96 |
+
|
97 |
+
# No need to convert to BGR and then read it again
|
98 |
+
target_img = image_np.astype(float)/256
|
99 |
+
source_img = palette.astype(float)/256
|
100 |
+
output_img = match_color(target_img, source_img)
|
101 |
+
output_img = (output_img * 255).astype(np.uint8)
|
102 |
+
imsave('result.jpg', output_img)
|
103 |
+
return output_img
|
recolorPaletteBasedTransfer.py
CHANGED
@@ -19,7 +19,7 @@ def extract_palette(image, n_colors=5):
|
|
19 |
pixels = image.reshape(-1, 3)
|
20 |
|
21 |
# Apply KMeans clustering to find the most dominant colors
|
22 |
-
kmeans = KMeans(n_clusters=n_colors)
|
23 |
kmeans.fit(pixels)
|
24 |
|
25 |
# Get the RGB values of the clusters' centers
|
@@ -70,8 +70,13 @@ def palette_based_color_transfer(source_img, target_palette, n_colors=5):
|
|
70 |
# Extract the source palette
|
71 |
source_palette = extract_palette(source_img, n_colors)
|
72 |
|
|
|
|
|
|
|
|
|
73 |
# Perform color mapping
|
74 |
-
|
|
|
75 |
|
76 |
return recolored_img
|
77 |
|
|
|
19 |
pixels = image.reshape(-1, 3)
|
20 |
|
21 |
# Apply KMeans clustering to find the most dominant colors
|
22 |
+
kmeans = KMeans(n_clusters=n_colors, n_init='auto')
|
23 |
kmeans.fit(pixels)
|
24 |
|
25 |
# Get the RGB values of the clusters' centers
|
|
|
70 |
# Extract the source palette
|
71 |
source_palette = extract_palette(source_img, n_colors)
|
72 |
|
73 |
+
# Ensure target_palette has the same number of colors as source_palette
|
74 |
+
while len(target_palette) < n_colors:
|
75 |
+
target_palette += target_palette
|
76 |
+
|
77 |
# Perform color mapping
|
78 |
+
|
79 |
+
recolored_img = map_colors(source_img, source_palette, target_palette[:n_colors])
|
80 |
|
81 |
return recolored_img
|
82 |
|
recolorReinhardV2Algo.py
CHANGED
@@ -37,12 +37,45 @@ def color_transfer(source, target):
|
|
37 |
|
38 |
return result
|
39 |
|
40 |
-
# Load source and target images
|
41 |
-
source_img = cv2.imread("estampa.jpg")
|
42 |
-
target_img = cv2.imread("cor.jpg")
|
43 |
|
44 |
-
# Perform color transfer
|
45 |
-
transferred_img = color_transfer(source_img, target_img)
|
46 |
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
return result
|
39 |
|
|
|
|
|
|
|
40 |
|
|
|
|
|
41 |
|
42 |
+
def create_target_image(hex_colors):
|
43 |
+
# Convert hex colors to RGB
|
44 |
+
rgb_colors = [tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) for hex_color in hex_colors]
|
45 |
+
|
46 |
+
# Create an image with the RGB colors
|
47 |
+
target_image = np.zeros((100, len(rgb_colors), 3), dtype=np.uint8)
|
48 |
+
for i, rgb_color in enumerate(rgb_colors):
|
49 |
+
target_image[:, i] = rgb_color
|
50 |
+
|
51 |
+
return target_image
|
52 |
+
|
53 |
+
|
54 |
+
# # Load source and target images
|
55 |
+
# source_img = cv2.imread("estampa.jpg")
|
56 |
+
# target_img = cv2.imread("cor.jpg")
|
57 |
+
|
58 |
+
|
59 |
+
# hex_colors = ['ff0000', '00ff00', '0000ff'] # Example hex colors
|
60 |
+
# target_img = create_target_image(hex_colors)
|
61 |
+
|
62 |
+
# image_bytes = io.BytesIO(source_img)
|
63 |
+
# image_np = np.array(image)
|
64 |
+
|
65 |
+
# # Perform color transfer
|
66 |
+
# transferred_img = color_transfer(source_img, target_img)
|
67 |
+
|
68 |
+
# # Return the transferred image for visualization
|
69 |
+
# cv2.imwrite("result.jpg", transferred_img)
|
70 |
+
|
71 |
+
def recolor(image_np, colors):
|
72 |
+
colors = [color.replace('#', '') for color in colors]
|
73 |
+
|
74 |
+
target_img = create_target_image(colors)
|
75 |
+
source_bgr = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
|
76 |
+
transferred_img = color_transfer(source_bgr, target_img)
|
77 |
+
cv2.imwrite("result.jpg", transferred_img)
|
78 |
+
return transferred_img
|
79 |
+
|
80 |
+
|
81 |
+
|
server.py
CHANGED
@@ -12,6 +12,8 @@ import recolorOTAlgo
|
|
12 |
import recolorTransferAlgo
|
13 |
import recolorLumaConverterAlgo
|
14 |
import recolorPaletteBasedTransfer
|
|
|
|
|
15 |
|
16 |
app = FastAPI()
|
17 |
|
@@ -82,20 +84,31 @@ async def recolor(file: UploadFile = File(...), colors: str = Form(...), model:
|
|
82 |
image_np = np.array(image)
|
83 |
|
84 |
if method == "CCA":
|
|
|
85 |
#Characteristic Color Analysis
|
86 |
recolorReinhardAlgo.recolor(image_np, colors)
|
87 |
elif method == "OTA":
|
|
|
88 |
#Optimal Transport Algorithm transfer
|
89 |
recolorOTAlgo.recolor(image_np, colors)
|
90 |
elif method =="KMEANS":
|
|
|
91 |
#K-means clustering transfer
|
92 |
recolorTransferAlgo.recolor(image_np, colors)
|
93 |
elif method == "LUMA":
|
|
|
94 |
#Luma converter transfer
|
95 |
recolorLumaConverterAlgo.remap_image_colors(image_np, colors)
|
96 |
elif method == "palette":
|
97 |
#palette transfer
|
|
|
98 |
recolorPaletteBasedTransfer.recolor(image_np, colors)
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
img_file = open("./result.jpg", "rb")
|
100 |
return StreamingResponse(img_file, media_type="image/jpeg")
|
101 |
@app.get("/test/")
|
|
|
12 |
import recolorTransferAlgo
|
13 |
import recolorLumaConverterAlgo
|
14 |
import recolorPaletteBasedTransfer
|
15 |
+
import recolorReinhardV2Algo
|
16 |
+
import recolorLinearColorTransfer
|
17 |
|
18 |
app = FastAPI()
|
19 |
|
|
|
84 |
image_np = np.array(image)
|
85 |
|
86 |
if method == "CCA":
|
87 |
+
print('CCA generated')
|
88 |
#Characteristic Color Analysis
|
89 |
recolorReinhardAlgo.recolor(image_np, colors)
|
90 |
elif method == "OTA":
|
91 |
+
print('OTA generated')
|
92 |
#Optimal Transport Algorithm transfer
|
93 |
recolorOTAlgo.recolor(image_np, colors)
|
94 |
elif method =="KMEANS":
|
95 |
+
print('KMEANS generated')
|
96 |
#K-means clustering transfer
|
97 |
recolorTransferAlgo.recolor(image_np, colors)
|
98 |
elif method == "LUMA":
|
99 |
+
print('Luma generated')
|
100 |
#Luma converter transfer
|
101 |
recolorLumaConverterAlgo.remap_image_colors(image_np, colors)
|
102 |
elif method == "palette":
|
103 |
#palette transfer
|
104 |
+
print('palette generated')
|
105 |
recolorPaletteBasedTransfer.recolor(image_np, colors)
|
106 |
+
elif method == "Reinhardv2":
|
107 |
+
print('Reinhardv2 generated')
|
108 |
+
recolorReinhardV2Algo.recolor(image_np, colors)
|
109 |
+
elif method == "LinearColorTransfer":
|
110 |
+
print('LinearColorTransfer generated')
|
111 |
+
recolorLinearColorTransfer.recolor(image_np, colors)
|
112 |
img_file = open("./result.jpg", "rb")
|
113 |
return StreamingResponse(img_file, media_type="image/jpeg")
|
114 |
@app.get("/test/")
|
todo.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
* add more two funcoes de troca de cor
|
2 |
*add invert colors
|
3 |
-
*check file type
|
4 |
*mask
|
5 |
|
6 |
**added:
|
7 |
-
recolor
|
8 |
|
9 |
`
|
10 |
source ./env/bin/activate
|
@@ -12,9 +12,5 @@ source ./env/bin/activate
|
|
12 |
#how to run:
|
13 |
#source env/bin/activate
|
14 |
#uvicorn server:app --reload
|
|
|
15 |
`
|
16 |
-
|
17 |
-
|
18 |
-
ERRORS TODO:
|
19 |
-
PALETTE ALGO IS WORKING BUT GIVING WARNINGS AND ERRORS.
|
20 |
-
DOMINANT COLOR IS BROKEN
|
|
|
1 |
* add more two funcoes de troca de cor
|
2 |
*add invert colors
|
3 |
+
*check file type (maybe not needed?)
|
4 |
*mask
|
5 |
|
6 |
**added:
|
7 |
+
recolor linear transfer. => need to add to the backend.
|
8 |
|
9 |
`
|
10 |
source ./env/bin/activate
|
|
|
12 |
#how to run:
|
13 |
#source env/bin/activate
|
14 |
#uvicorn server:app --reload
|
15 |
+
#docker run -p 4201:7860 farm-recolor
|
16 |
`
|
|
|
|
|
|
|
|
|
|