File size: 13,221 Bytes
542c815
3f8e328
542c815
 
 
a888400
d6e753e
 
1507964
8a357d1
542c815
3267028
bc27880
018621a
3267028
b98efed
542c815
b28fdb1
 
 
d566dd2
 
b28fdb1
de5919b
b28fdb1
 
 
 
 
 
7b95668
 
 
b28fdb1
6559cd2
b28fdb1
 
 
 
7b95668
 
b28fdb1
 
 
 
fe0144b
de5919b
91c9afc
 
b28fdb1
 
 
 
7b95668
 
b28fdb1
 
 
a634010
fe0144b
a634010
91c9afc
 
b28fdb1
 
7b95668
b28fdb1
 
7b95668
b28fdb1
 
 
 
 
 
6b88ea3
33ea116
6b88ea3
 
 
 
e94843d
d6a88a0
6b88ea3
 
 
 
 
 
 
 
771ec10
6b88ea3
 
 
 
 
 
 
 
 
 
 
771ec10
6b88ea3
 
 
 
1eead92
6b88ea3
 
b28fdb1
bc27880
 
 
 
 
 
 
 
ddf8bbd
 
bc27880
33ea116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bc27880
 
ade8740
bc27880
 
33ea116
 
bc27880
 
25b3a5d
4a2e114
beddc35
c7f0514
beddc35
bc27880
 
 
 
 
 
 
 
 
15895f8
bc27880
 
 
 
81a4fa1
 
ecca03e
 
bc27880
 
 
 
5ed7ed1
 
a44c5d4
5ed7ed1
bc27880
c2497a1
 
 
 
82e40b3
bc27880
 
 
 
 
 
82e40b3
9f01959
91990cf
bc27880
 
 
 
 
542c815
 
 
988f91c
 
542c815
 
 
4f80f3b
542c815
 
1605763
fd5cf68
542c815
 
4f80f3b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542c815
bc27880
15895f8
b28fdb1
b6628b0
fd5cf68
d20daf3
fd5cf68
bc27880
68112f8
 
542c815
 
d909bca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542c815
d909bca
 
 
 
542c815
d909bca
 
c530952
d909bca
c530952
 
 
77e7904
 
 
 
c530952
 
77e7904
 
 
6ca28a8
d909bca
68112f8
 
bc27880
 
4977297
8766abc
 
 
15895f8
 
b6628b0
4f80f3b
 
 
15895f8
bc27880
d909bca
 
 
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
import numpy as np
import torch
import torch.nn.functional as F
from torchvision.transforms.functional import normalize
import gradio as gr
from gradio_imageslider import ImageSlider
from briarmbg import BriaRMBG
import PIL
from PIL import Image, ImageDraw, ImageFont
from typing import Tuple



net = BriaRMBG.from_pretrained("briaai/RMBG-1.4")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
net.to(device)

def draw_ruler(image, actual_height_in_inches = 13, dpi=300, unit="in", color="black"):

    # Load the plant image in its original size
    canvas = image
    plant_width, plant_height = canvas.size

    #actual_height_in_inches = 13       #only do the changes in this and generate the images ,,,,,, 
    #think about approximate height of plant suppose it is 8.3 inch so mention here 9 .and run the code 

    # Calculate pixels per inch based on the plant image's pixel height
    pixels_per_inch = plant_height / actual_height_in_inches

    # Create a blank canvas larger than the plant image to accommodate rulers
    canvas_width = plant_width #+ 150  # 50 pixels extra for the left ruler
    canvas_height = plant_height #+ 150  # 50 pixels extra for the bottom ruler
    #canvas = Image.new('RGB', (canvas_width, canvas_height), 'white')
    draw = ImageDraw.Draw(canvas)
    font = ImageFont.load_default(size=60)

    # for drawing scale value on vertical side ................   0,  0.5, 1, 1.5, 2, 2.5, 3, 3.5...................so on  
    for i in range(0, int(plant_height / (pixels_per_inch * 0.5)) + 1):
        # Calculate position and inch value
        #y_position = canvas_height - 150 - int(i * pixels_per_inch * 0.5)
        y_position = canvas_height - 0 - int(i * pixels_per_inch * 0.5)
        inch_value = i * 0.5

        # Draw tick mark and add text label every 1 inch for better readability
        draw.line((0, y_position, 10, y_position), fill='black')
        if inch_value.is_integer() and inch_value % 5 == 0:  # Display labels only at whole numbers
            draw.text((15, y_position - 5), f"{int(inch_value)} in", fill='black',font=font)
        #else:
           # draw.text((15, y_position - 5), f"{inch_value:.1f} in", fill='black',font=font)

    # for drawing scale value on horizontal side ................   0,  0.5, 1, 1.5, 2, 2.5, 3, 3.5...................so on  
    for i in range(0, int(plant_width / (pixels_per_inch * 0.5)) + 1):
        # Calculate position and inch value
        #x_position = 150 + int(i * pixels_per_inch * 0.5)
        x_position = 0 + int(i * pixels_per_inch * 0.5)
        inch_value = i * 0.5

        # Draw tick mark and add text label every 1 inch for better readability
        draw.line((x_position, canvas_height - 40, x_position, canvas_height), fill='black')
        if inch_value.is_integer() and inch_value % 5 == 0:  # Display labels only at whole numbers
            draw.text((x_position, canvas_height - 65), f"{int(inch_value)} in", fill='black',font=font)
        #else:
            #draw.text((x_position, canvas_height - 25), f"{inch_value:.1f} in", fill='black',font=font)
            
    # Position to paste the plant image on the canvas (leaving space for rulers)
    #plant_position = (150, canvas_height - plant_height - 150)

    # Paste the original plant image onto the canvas without resizing
    #canvas.paste(plant_image, plant_position)

    # Save the final image with the plant and rulers
    #canvas.save('image_with_plant_and_rulers_high_quality_ONE.png')

    #print("The image with the plant and rulers has been saved at original quality.")
    return canvas;

def draw_ruler0(image, dpi=300, unit="in", color="black"):

    # Define the pot dimensions and distance from camera
    pot_diameter_inches = 4
    pot_height_inches = 6
    distance_from_camera_feet = 0.5
    zoom_level = 1  # Zoom level

    # Convert distance from feet to inches
    distance_from_camera_inches = distance_from_camera_feet * 12

    # Calculate the scale factor (assuming a simple pinhole camera model)
    # Scale factor = (actual height of the object) / (height of the object in the image)
    # Adjust for zoom level
    scale_factor = (pot_height_inches / distance_from_camera_inches) * zoom_level
    print ("scale factor:",scale_factor)

    # Draw the scale on the image
    draw = ImageDraw.Draw(image)
    font = ImageFont.load_default()

    # Define the position and size of the scale
    scale_length_pixels = int(pot_height_inches / scale_factor)
    scale_position = (50, 50)  # Adjust as needed

    # Draw the scale line
    draw.line((scale_position[0], scale_position[1], scale_position[0], scale_position[1] + scale_length_pixels), fill="red", width=5)
    print("line:",(scale_position[0], scale_position[1], scale_position[0], scale_position[1] + scale_length_pixels))

    # Add text label for the scale
    draw.text((scale_position[0] + 10, scale_position[1] + scale_length_pixels // 2), f"{pot_height_inches} inches", fill="red", font=font)

    return image


def draw_ruler1(image, dpi=300, unit="in", color="black"):
    """
    Draws a ruler on the top and left edges of an image.
    Args:
        image: The PIL Image object to draw on.
        dpi: The DPI of the image (default 300).
        unit: The unit of measurement (default "in").
        color: The color of the ruler (default "black").
    """
    #dpi = image.info.get("dpi", (72, 72))
    #dpi = dpi[0] if isinstance(dpi, tuple) else dpi

    # Define the pot dimensions and distance from camera
    pot_diameter_inches = 4
    pot_height_inches = 6
    distance_from_camera_feet = 3
    zoom_level = 0.5  # Zoom level

    # Convert distance from feet to inches
    distance_from_camera_inches = distance_from_camera_feet * 12

    # Calculate the scale factor (assuming a simple pinhole camera model)
    # Scale factor = (actual height of the object) / (height of the object in the image)
    # Adjust for zoom level
    scale_factor = (pot_height_inches / distance_from_camera_inches) * zoom_level
    scale_length_pixels = int(pot_height_inches / scale_factor)
    print ("scale factor:",scale_factor,"scale_length_pixels:",scale_length_pixels)

    
    draw = ImageDraw.Draw(image)
    width, height = image.size
    font = ImageFont.load_default(size=60)

    # Draw top ruler
    #for i in range(0, width, int(dpi)):
    for i in range(0, width, scale_length_pixels):
        x = i
        draw.line((x, 0, x, 10), fill=color)
        if i % int(scale_length_pixels) == 0:
            if scale_length_pixels< 70 :
                draw.text((x, 12), str(i // scale_length_pixels), fill=color, font=font)
            if scale_length_pixels > 70 and i % 5 == 0:
                draw.text((x, 12), str(i // scale_length_pixels), fill=color, font=font)

    # Draw left ruler
    for i in range(0, height, int(dpi)):
        y = i
        draw.line((0, y, 10, y), fill=color)
        if i % int(dpi) == 0:
            if i != 0:
                 draw.text((12, y), str(i // dpi), fill=color, font=font)
            
    draw.text((100, y-60), "inch", fill=color, font=font)

    return image
    
def mm_to_pixels(mm, dpi):
    if dpi is None:
        dpi = 72  # Default DPI value
    if mm is None:
        mm = 0  # Default mm value
    return int(mm * dpi / 25.4)

def crop_image(image, left_mm, top_mm, right_mm, bottom_mm):
    # Open the image file
    #img = Image.open(image)
    img = image
    print("img.width:",img.width,"img.height:",img.height)

    # Get the image DPI (dots per inch)
    #dpi = img.info.get('dpi', (72, 72))[0]  # Default to 72 DPI if not available
    # Get the DPI value as a single number
    dpi = img.info.get("dpi", (72, 72))
    dpi = dpi[0] if isinstance(dpi, tuple) else dpi
    print ("dpi:",dpi)
    
    # Convert mm to pixels
    left = mm_to_pixels(left_mm, dpi)
    top = mm_to_pixels(top_mm, dpi)
    right = mm_to_pixels(right_mm, dpi)
    bottom = mm_to_pixels(bottom_mm, dpi)
    print("left:",left,"top:",top,"right:",right,"bottom:",bottom)
    if img.width - right <= left :
        right=img.width-left-1
    
    # Crop the image
    cropped_img = img.crop((left, top, img.width - right, img.height - bottom))
    
    return cropped_img
    
def resize_image(image):
    image = image.convert('RGB')
    model_input_size = (1024, 1024)
    image = image.resize(model_input_size, Image.BILINEAR)
    return image


def process(image,left_mm, top_mm, right_mm, bottom_mm, ruler, resize,actual_height_in_inches,background):

    # prepare input
    orig_image = Image.fromarray(image)
    print("orig size:",orig_image.size)
    w,h = orig_im_size = orig_image.size
    image = resize_image(orig_image)
    new_im=image;

    if background:
        # remove background
        im_np = np.array(image)
        im_tensor = torch.tensor(im_np, dtype=torch.float32).permute(2,0,1)
        im_tensor = torch.unsqueeze(im_tensor,0)
        im_tensor = torch.divide(im_tensor,255.0)
        im_tensor = normalize(im_tensor,[0.5,0.5,0.5],[1.0,1.0,1.0])
        if torch.cuda.is_available():
            im_tensor=im_tensor.cuda()

        #inference
        result=net(im_tensor)
        # post process
        result = torch.squeeze(F.interpolate(result[0][0], size=(h,w), mode='bilinear') ,0)
        ma = torch.max(result)
        mi = torch.min(result)
        result = (result-mi)/(ma-mi)    
        # image to pil
        im_array = (result*255).cpu().data.numpy().astype(np.uint8)
        pil_im = Image.fromarray(np.squeeze(im_array))
        # paste the mask on the original image
        new_im = Image.new("RGBA", pil_im.size, (0,0,0,0))
        new_im.paste(orig_image, mask=pil_im)
        # new_orig_image = orig_image.convert('RGBA')
    else:
        new_im=image;

    new_im= crop_image(new_im, left_mm, top_mm, right_mm, bottom_mm)
    if ruler:
        new_im = draw_ruler(new_im,actual_height_in_inches)
        
    if resize is not None and resize > 0:
        new_im = new_im.resize( [int(resize * s) for s in new_im.size],Image.Resampling.LANCZOS )
        print("resize:",new_im.size)

    return new_im
    # return [new_orig_image, new_im]


# block = gr.Blocks().queue()

# with block:
#     gr.Markdown("## BRIA RMBG 1.4")
#     gr.HTML('''
#       <p style="margin-bottom: 10px; font-size: 94%">
#         This is a demo for BRIA RMBG 1.4 that using
#         <a href="https://huggingface.co/briaai/RMBG-1.4" target="_blank">BRIA RMBG-1.4 image matting model</a> as backbone. 
#       </p>
#     ''')
#     with gr.Row():
#         with gr.Column():
#             input_image = gr.Image(sources=None, type="pil") # None for upload, ctrl+v and webcam
#             # input_image = gr.Image(sources=None, type="numpy") # None for upload, ctrl+v and webcam
#             run_button = gr.Button(value="Run")
            
#         with gr.Column():
#             result_gallery = gr.Gallery(label='Output', show_label=False, elem_id="gallery", columns=[1], height='auto')
#     ips = [input_image]
#     run_button.click(fn=process, inputs=ips, outputs=[result_gallery])

# block.launch(debug = True)

# block = gr.Blocks().queue()

gr.Markdown("## BRIA RMBG 1.4")
gr.HTML('''
  <p style="margin-bottom: 10px; font-size: 94%">
    This app is leveraging the RMBG v1.4 model which is developed on the IS-Net enhanced with unique training scheme and proprietary dataset.
    These modifications significantly improve the model’s accuracy and effectiveness in diverse image-processing scenarios.
    This is an internal tool being tested for rootsraja.in product images at
    <a href="https://huggingface.co/spaces/laitkor/product-image" target="_blank">Rootsraja internal product tool using an image matting model</a> as backbone. 
  </p>
''')
title = "Background Removal, Cropping, Resizing, Ruler and scaling"
description = r"""<a href="https://huggingface.co/spaces/laitkor/product-image" target="_blank">Rootsraja internal product tool<br> 
To use upload your image and wait. Read more at model card <a href='https://huggingface.co/briaai/RMBG-1.4' target='_blank'><b>briaai/RMBG-1.4</b></a>.<br>
"""
examples = [['./input.jpg'],]
# output = ImageSlider(position=0.5,label='Image without background', type="pil", show_download_button=True)
# demo = gr.Interface(fn=process,inputs="image", outputs=output, examples=examples, title=title, description=description)
demo = gr.Interface(fn=process,
                    inputs=[
                        gr.Image(type="numpy", label="Upload Image"),
                        gr.Number(label="Left Crop (mm)",value=0),
                        gr.Number(label="Top Crop (mm)",value=0),
                        gr.Number(label="Right Crop (mm)",value=0),
                        gr.Number(label="Bottom Crop (mm)",value=0),
                        gr.Checkbox(label="Ruler!"),
                        gr.Number(label="Resize (between 0.1 and 0.9)",value=0),
                        gr.Number(label="Plant height in inches",value=0),
                        gr.Checkbox(label="Remove Background?")

                    ],
                    outputs="image", examples=examples, title=title, description=description)

if __name__ == "__main__":
    demo.launch(share=False)