utils.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. # copyright (c) 2024 PaddlePaddle Authors. All Rights Reserve.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import asyncio
  15. import base64
  16. import io
  17. import uuid
  18. from functools import partial
  19. from typing import Awaitable, Callable, List, Optional, TypeVar
  20. from urllib.parse import urlparse
  21. import aiohttp
  22. import cv2
  23. import fitz
  24. import numpy as np
  25. import pandas as pd
  26. import yarl
  27. from PIL import Image
  28. from typing_extensions import ParamSpec
  29. _P = ParamSpec("_P")
  30. _R = TypeVar("_R")
  31. def generate_log_id() -> str:
  32. return str(uuid.uuid4())
  33. def is_url(s: str) -> bool:
  34. if not (s.startswith("http://") or s.startswith("https://")):
  35. # Quick rejection
  36. return False
  37. result = urlparse(s)
  38. return all([result.scheme, result.netloc]) and result.scheme in ("http", "https")
  39. async def get_raw_bytes(file: str, session: aiohttp.ClientSession) -> bytes:
  40. if is_url(file):
  41. async with session.get(yarl.URL(file, encoded=True)) as resp:
  42. return await resp.read()
  43. else:
  44. return base64.b64decode(file)
  45. def image_bytes_to_array(data: bytes) -> np.ndarray:
  46. return cv2.imdecode(np.frombuffer(data, np.uint8), cv2.IMREAD_COLOR)
  47. def image_to_base64(image: Image.Image) -> str:
  48. with io.BytesIO() as f:
  49. image.save(f, format="JPEG")
  50. image_base64 = base64.b64encode(f.getvalue()).decode("ascii")
  51. return image_base64
  52. def csv_bytes_to_data_frame(data: bytes) -> pd.DataFrame:
  53. with io.StringIO(data.decode("utf-8")) as f:
  54. df = pd.read_csv(f)
  55. return df
  56. def data_frame_to_base64(df: str) -> str:
  57. return base64.b64encode(df.to_csv().encode("utf-8")).decode("ascii")
  58. def read_pdf(
  59. bytes_: bytes, resize: bool = False, max_num_imgs: Optional[int] = None
  60. ) -> List[np.ndarray]:
  61. images: List[np.ndarray] = []
  62. img_size = None
  63. with fitz.open("pdf", bytes_) as doc:
  64. for page in doc:
  65. if max_num_imgs is not None and len(images) >= max_num_imgs:
  66. break
  67. # TODO: Do not always use zoom=2.0
  68. zoom = 2.0
  69. deg = 0
  70. mat = fitz.Matrix(zoom, zoom).prerotate(deg)
  71. pixmap = page.get_pixmap(matrix=mat, alpha=False)
  72. image = np.frombuffer(pixmap.samples, dtype=np.uint8).reshape(
  73. pixmap.h, pixmap.w, pixmap.n
  74. )
  75. image = np.ascontiguousarray(image[..., ::-1])
  76. if resize:
  77. if img_size is None:
  78. img_size = (image.shape[1], image.shape[0])
  79. else:
  80. if (image.shape[1], image.shape[0]) != img_size:
  81. image = cv2.resize(image, img_size)
  82. images.append(image)
  83. return images
  84. def call_async(
  85. func: Callable[_P, _R], /, *args: _P.args, **kwargs: _P.kwargs
  86. ) -> Awaitable[_R]:
  87. return asyncio.get_running_loop().run_in_executor(
  88. None, partial(func, *args, **kwargs)
  89. )