Skip to content

Commit b4f8ea4

Browse files
committed
add __init__.py and docstrings
1 parent e11f0cd commit b4f8ea4

File tree

3 files changed

+136
-62
lines changed

3 files changed

+136
-62
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""
2+
__init__.py file for screenshot_scraping folder
3+
"""
4+
5+
6+
from .screenshot_preparation import take_screenshot, select_area_with_opencv, select_area_with_ipywidget, crop_image
7+
from .text_detection import detect_text
8+

scrapegraphai/sreenshot_scraping/screenshot_preparation.py

Lines changed: 114 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,116 +3,140 @@
33

44
from io import BytesIO
55
from PIL import Image, ImageGrab
6-
import os
76

87

9-
async def take_screenshot(url:str, image_name:str=None, quality:int=100):
8+
async def take_screenshot(url: str, save_path: str = None, quality: int = 100):
9+
"""
10+
Takes a screenshot of a webpage at the specified URL and saves it if the save_path is specified.
11+
Parameters:
12+
url (str): The URL of the webpage to take a screenshot of.
13+
save_path (str): The path to save the screenshot to. Defaults to None.
14+
quality (int): The quality of the jpeg image, between 1 and 100. Defaults to 100.
15+
Returns:
16+
PIL.Image: The screenshot of the webpage as a PIL Image object.
17+
"""
18+
1019
async with async_playwright() as p:
1120
browser = await p.chromium.launch(headless=True)
1221
page = await browser.new_page()
1322
await page.goto(url)
14-
save_path=None
15-
if image_name is not None:
16-
dir_path = os.path.abspath('')
17-
save_path = dir_path + "/scrapegraphai/sreenshot_scraping/saved_screenshots/" + image_name
18-
image_bytes = await page.screenshot(path=save_path,type="jpeg",full_page=True,quality=quality)
23+
image_bytes = await page.screenshot(path=save_path, type="jpeg", full_page=True, quality=quality)
1924
await browser.close()
2025
return Image.open(BytesIO(image_bytes))
2126

2227

2328
def select_area_with_opencv(image):
29+
"""
30+
Allows you to manually select an image area using OpenCV. It is recommended to use this function if your project is on your computer, otherwise use select_area_with_ipywidget().
31+
Parameters:
32+
image (PIL.Image): The image from which to select an area.
33+
Returns:
34+
A tuple containing the LEFT, TOP, RIGHT, and BOTTOM coordinates of the selected area.
35+
"""
36+
2437
import cv2 as cv
2538
import numpy as np
2639

2740
fullscreen_screenshot = ImageGrab.grab()
28-
dw, dh=fullscreen_screenshot.size
41+
dw, dh = fullscreen_screenshot.size
2942

3043
def draw_selection_rectanlge(event, x, y, flags, param):
31-
global ix,iy,drawing,overlay ,img
44+
global ix, iy, drawing, overlay, img
3245
if event == cv.EVENT_LBUTTONDOWN:
3346
drawing = True
34-
ix,iy = x,y
47+
ix, iy = x, y
3548
elif event == cv.EVENT_MOUSEMOVE:
3649
if drawing == True:
3750
cv.rectangle(img, (ix, iy), (x, y), (41, 215, 162), -1)
38-
cv.putText(img, 'PRESS ANY KEY TO SELECT THIS AREA', (ix, iy-10), cv.FONT_HERSHEY_SIMPLEX, 1.5, (55,46,252), 5)
39-
img=cv.addWeighted(overlay, alpha, img, 1 - alpha, 0)
51+
cv.putText(img, 'PRESS ANY KEY TO SELECT THIS AREA', (ix,
52+
iy-10), cv.FONT_HERSHEY_SIMPLEX, 1.5, (55, 46, 252), 5)
53+
img = cv.addWeighted(overlay, alpha, img, 1 - alpha, 0)
4054
elif event == cv.EVENT_LBUTTONUP:
41-
global LEFT,TOP,RIGHT,BOTTOM
42-
55+
global LEFT, TOP, RIGHT, BOTTOM
56+
4357
drawing = False
44-
if ix<x:
45-
LEFT=int(ix)
46-
RIGHT=int(x)
58+
if ix < x:
59+
LEFT = int(ix)
60+
RIGHT = int(x)
4761
else:
48-
LEFT=int(x)
49-
RIGHT=int(ix)
50-
if iy<y:
51-
TOP=int(iy)
52-
BOTTOM=int(y)
62+
LEFT = int(x)
63+
RIGHT = int(ix)
64+
if iy < y:
65+
TOP = int(iy)
66+
BOTTOM = int(y)
5367
else:
54-
TOP=int(y)
55-
BOTTOM=int(iy)
68+
TOP = int(y)
69+
BOTTOM = int(iy)
5670

57-
global drawing,ix,iy,overlay,img
71+
global drawing, ix, iy, overlay, img
5872
drawing = False
59-
ix,iy = -1,-1
73+
ix, iy = -1, -1
6074

61-
img =np.array(image)
75+
img = np.array(image)
6276
img = cv.cvtColor(img, cv.COLOR_RGB2BGR)
6377

64-
img=cv.rectangle(img, (0, 0), (image.size[0], image.size[1]), (0,0,255), 10)
65-
img=cv.putText(img, 'SELECT AN AREA', (int(image.size[0]*0.3), 100), cv.FONT_HERSHEY_SIMPLEX, 2, (0,0,255), 5)
66-
78+
img = cv.rectangle(
79+
img, (0, 0), (image.size[0], image.size[1]), (0, 0, 255), 10)
80+
img = cv.putText(img, 'SELECT AN AREA', (int(
81+
image.size[0]*0.3), 100), cv.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 5)
82+
6783
overlay = img.copy()
6884
alpha = 0.3
6985

7086
while True:
71-
cv.namedWindow('SELECT AREA', cv.WINDOW_KEEPRATIO)
87+
cv.namedWindow('SELECT AREA', cv.WINDOW_KEEPRATIO)
7288
cv.setMouseCallback('SELECT AREA', draw_selection_rectanlge)
73-
cv.resizeWindow('SELECT AREA', int(image.size[0]/(image.size[1]/dh)), dh)
74-
75-
cv.imshow('SELECT AREA',img)
89+
cv.resizeWindow('SELECT AREA', int(
90+
image.size[0]/(image.size[1]/dh)), dh)
91+
92+
cv.imshow('SELECT AREA', img)
7693

7794
if cv.waitKey(20) > -1:
7895
break
79-
96+
8097
cv.destroyAllWindows()
8198
return LEFT, TOP, RIGHT, BOTTOM
8299

100+
83101
def select_area_with_ipywidget(image):
102+
"""
103+
Allows you to manually select an image area using ipywidgets. It is recommended to use this function if your project is in Google Colab, Kaggle or other similar platform, otherwise use select_area_with_opencv().
104+
Parameters:
105+
image (PIL Image): The input image.
106+
Returns:
107+
None
108+
"""
109+
84110
import matplotlib.pyplot as plt
85111
import numpy as np
86112
from ipywidgets import interact, IntSlider
87113
import ipywidgets as widgets
88114
from PIL import Image
89115

90-
91-
# Load an image
92-
# image_path = 'piping-yes-when-running-scripts-from-curl.jpeg' # Replace with your image path
93-
# image = Image.open(image_path)
94116
img_array = np.array(image)
95117

96118
print(img_array.shape)
97119

98-
def update_plot(top_bottom,left_right,image_size):
99-
plt.figure(figsize = (image_size,image_size))
120+
def update_plot(top_bottom, left_right, image_size):
121+
plt.figure(figsize=(image_size, image_size))
100122
plt.imshow(img_array)
101123
plt.axvline(x=left_right[0], color='blue', linewidth=1)
102-
plt.text(left_right[0]+1,-25,'LEFT',rotation=90,color='blue')
124+
plt.text(left_right[0]+1, -25, 'LEFT', rotation=90, color='blue')
103125
plt.axvline(x=left_right[1], color='red', linewidth=1)
104-
plt.text(left_right[1]+1,-25,'RIGHT',rotation=90, color='red')
105-
106-
107-
plt.axhline(y=img_array.shape[0]-top_bottom[0], color='green', linewidth=1)
108-
plt.text(-100,img_array.shape[0]-top_bottom[0]+1,'BOTTOM', color='green')
109-
plt.axhline(y=img_array.shape[0]-top_bottom[1], color='darkorange', linewidth=1)
110-
plt.text(-100,img_array.shape[0]-top_bottom[1]+1,'TOP', color='darkorange')
111-
plt.axis('off') # Hide axes
126+
plt.text(left_right[1]+1, -25, 'RIGHT', rotation=90, color='red')
127+
128+
plt.axhline(y=img_array.shape[0] -
129+
top_bottom[0], color='green', linewidth=1)
130+
plt.text(-100, img_array.shape[0] -
131+
top_bottom[0]+1, 'BOTTOM', color='green')
132+
plt.axhline(y=img_array.shape[0]-top_bottom[1],
133+
color='darkorange', linewidth=1)
134+
plt.text(-100, img_array.shape[0] -
135+
top_bottom[1]+1, 'TOP', color='darkorange')
136+
plt.axis('off')
112137
plt.show()
113138

114-
115-
top_bottom_slider=widgets.IntRangeSlider(
139+
top_bottom_slider = widgets.IntRangeSlider(
116140
value=[int(img_array.shape[0]*0.25), int(img_array.shape[0]*0.75)],
117141
min=0,
118142
max=img_array.shape[0],
@@ -125,7 +149,7 @@ def update_plot(top_bottom,left_right,image_size):
125149
readout_format='d',
126150
)
127151

128-
left_right_slider=widgets.IntRangeSlider(
152+
left_right_slider = widgets.IntRangeSlider(
129153
value=[int(img_array.shape[1]*0.25), int(img_array.shape[1]*0.75)],
130154
min=0,
131155
max=img_array.shape[1],
@@ -137,7 +161,7 @@ def update_plot(top_bottom,left_right,image_size):
137161
readout=True,
138162
readout_format='d',
139163
)
140-
image_size_bt=widgets.BoundedIntText(
164+
image_size_bt = widgets.BoundedIntText(
141165
value=10,
142166
min=2,
143167
max=20,
@@ -146,11 +170,44 @@ def update_plot(top_bottom,left_right,image_size):
146170
disabled=False
147171
)
148172

149-
interact(update_plot,top_bottom= top_bottom_slider ,left_right=left_right_slider ,image_size=image_size_bt)
173+
interact(update_plot, top_bottom=top_bottom_slider,
174+
left_right=left_right_slider, image_size=image_size_bt)
175+
176+
177+
def crop_image(image, LEFT=None, TOP=None, RIGHT=None, BOTTOM=None, save_path: str = None):
178+
"""
179+
Crop an image using the specified coordinates.
180+
Parameters:
181+
image (PIL.Image): The image to be cropped.
182+
LEFT (int, optional): The x-coordinate of the left edge of the crop area. Defaults to None.
183+
TOP (int, optional): The y-coordinate of the top edge of the crop area. Defaults to None.
184+
RIGHT (int, optional): The x-coordinate of the right edge of the crop area. Defaults to None.
185+
BOTTOM (int, optional): The y-coordinate of the bottom edge of the crop area. Defaults to None.
186+
save_path (str, optional): The path to save the cropped image. Defaults to None.
187+
Returns:
188+
PIL.Image: The cropped image.
189+
Notes:
190+
If any of the coordinates (LEFT, TOP, RIGHT, BOTTOM) is None, it will be set to the corresponding edge of the image.
191+
If save_path is specified, the cropped image will be saved as a JPEG file at the specified path.
192+
"""
193+
194+
if LEFT is None:
195+
LEFT = 0
196+
if TOP is None:
197+
TOP = 0
198+
if RIGHT is None:
199+
RIGHT = image.size[0]
200+
if BOTTOM is None:
201+
BOTTOM = image.size[1]
202+
203+
croped_image = image.crop((LEFT, TOP, RIGHT, BOTTOM))
204+
if save_path is not None:
205+
from pathlib import Path
206+
croped_image.save(save_path, "JPEG")
150207

151-
def crop_image(image,TOP=None, BOTTOM=None, LEFT=None, RIGHT=None, save:bool=True):
152208
return image.crop((LEFT, TOP, RIGHT, BOTTOM))
153209

154210

155-
# image=asyncio.run(take_screenshot("https://unix.stackexchange.com/questions/690233/piping-yes-when-running-scripts-from-curl"))
211+
212+
# image=asyncio.run(take_screenshot("https://unix.stackexchange.com/questions/690233/piping-yes-when-running-scripts-from-curl", save_path="saved_screenshots/image.jpeg"))
156213
# print(select_area_with_opencv(image))
Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
1-
from PIL import Image
21
from surya.ocr import run_ocr
32
import numpy as np
43
from surya.model.detection.model import load_model as load_det_model, load_processor as load_det_processor
54
from surya.model.recognition.model import load_model as load_rec_model
65
from surya.model.recognition.processor import load_processor as load_rec_processor
76

87

9-
def DetectText(image, lahguages:list = ["en"]):
8+
def detect_text(image, lahguages: list = ["en"]):
9+
"""
10+
Detects and extracts text from a given image.
11+
Parameters:
12+
image (PIL Image): The input image to extract text from.
13+
lahguages (list): A list of languages to detect text in. Defaults to ["en"]. List of languages can be found here: https://github.com/VikParuchuri/surya/blob/master/surya/languages.py
14+
Returns:
15+
str: The extracted text from the image.
16+
Notes:
17+
Model weights will automatically download the first time you run this function.
18+
"""
1019

11-
# image = Image.fromarray(image_array.astype('uint8'), 'RGB')
1220
langs = lahguages
1321
det_processor, det_model = load_det_processor(), load_det_model()
1422
rec_model, rec_processor = load_rec_model(), load_rec_processor()
15-
predictions = run_ocr([image], [langs], det_model, det_processor, rec_model, rec_processor)
23+
predictions = run_ocr([image], [langs], det_model,
24+
det_processor, rec_model, rec_processor)
1625
text = "\n".join([line.text for line in predictions[0].text_lines])
1726
return text
1827

19-
# print(DetectText(Image.open("scrapegraphai\sreenshot_scraping\saved_screenshots\image.jpeg").crop((936,1967,1243,2246))))
28+

0 commit comments

Comments
 (0)