calango 2.2.8__tar.gz → 2.2.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: calango
3
- Version: 2.2.8
3
+ Version: 2.2.9
4
4
  Summary: It looks like calango
5
5
  Home-page: https://github.com/cereja-project/calango
6
6
  Author: Joab Leite
@@ -15,6 +15,17 @@ Requires-Dist: cereja
15
15
  Requires-Dist: opencv-python
16
16
  Requires-Dist: matplotlib
17
17
  Requires-Dist: numpy
18
+ Requires-Dist: scikit-learn
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: classifier
22
+ Dynamic: description
23
+ Dynamic: description-content-type
24
+ Dynamic: home-page
25
+ Dynamic: license-file
26
+ Dynamic: requires-dist
27
+ Dynamic: requires-python
28
+ Dynamic: summary
18
29
 
19
30
  # Calango Project
20
31
 
@@ -26,5 +26,7 @@ from . import settings
26
26
  from .devices import Mouse
27
27
  from .media import Image, VideoWriter, Video
28
28
 
29
- VERSION = "2.2.8.final.0"
29
+
30
+ VERSION = "2.2.9.final.0"
31
+
30
32
  __version__ = get_version_pep440_compliant(VERSION)
@@ -13,6 +13,7 @@ import cv2
13
13
  import numpy as np
14
14
  import logging
15
15
  from matplotlib import pyplot as plt
16
+ from sklearn.cluster import KMeans
16
17
 
17
18
  from .devices import Mouse
18
19
  from .settings import ON_COLAB_JUPYTER
@@ -520,7 +521,43 @@ class Image(np.ndarray):
520
521
  def save(self, p: str):
521
522
  cv2.imwrite(p, self)
522
523
  assert cj.Path(p).exists, f'Error saving image {p}'
524
+ def get_background_foreground_colors(self, k=2):
525
+ """
526
+ Função para determinar as cores RGB do background e do foreground em uma imagem.
527
+
528
+ Parâmetros:
529
+ image (np.array): imagem em formato de array numpy.
530
+ k (int): número de clusters para segmentação de cores (2 significa fundo e primeiro plano).
531
+
532
+ Retorna:
533
+ dict: dicionário com as cores RGB do background e do foreground.
534
+ """
535
+
536
+ # Redimensiona a imagem para acelerar o processamento
537
+ resize_dim = (300, 300)
538
+ image_resized = cv2.resize(self, resize_dim)
539
+ image_rgb = cv2.cvtColor(image_resized, cv2.COLOR_BGR2RGB)
540
+
541
+ # Converte a imagem para um array de pixels
542
+ pixels = image_rgb.reshape(-1, 3)
543
+
544
+ # Aplica KMeans para segmentar em duas cores (background e foreground)
545
+ kmeans = KMeans(n_clusters=k, random_state=0)
546
+ kmeans.fit(pixels)
547
+
548
+ # Obtém as cores dos clusters
549
+ cluster_colors = kmeans.cluster_centers_
550
+ cluster_labels, counts = np.unique(kmeans.labels_, return_counts=True)
523
551
 
552
+ # Identifica o background como a cor com mais pixels
553
+ background_idx = cluster_labels[np.argmax(counts)]
554
+ foreground_idx = cluster_labels[np.argmin(counts)]
555
+
556
+ # Converte as cores para inteiros RGB
557
+ background_rgb = tuple(map(int, cluster_colors[background_idx]))
558
+ foreground_rgb = tuple(map(int, cluster_colors[foreground_idx]))
559
+
560
+ return {"background_rgb": background_rgb, "foreground_rgb": foreground_rgb}
524
561
  def plot_colors_histogram(self):
525
562
  # tuple to select colors of each channel line
526
563
  colors = ("red", "green", "blue") if self._color_mode == 'RGB' else ('blue', 'green', 'red')
@@ -647,6 +684,24 @@ class Image(np.ndarray):
647
684
  dir_path = cj.Path(dir_path)
648
685
  return [cls(im_p.path) for im_p in dir_path.list_files(ext=ext)]
649
686
 
687
+ @classmethod
688
+ def _get_image_from_window(cls):
689
+ with cj.TempDir() as tmp:
690
+ while True:
691
+ window = yield
692
+ p = tmp.path.join('frame.bmp')
693
+ window.capture_image_bmp(p.path)
694
+ yield Image(p.path)
695
+
696
+ @classmethod
697
+ def from_window(cls, window: cj.Window) -> 'Image':
698
+ """
699
+ Get image from window
700
+ """
701
+ gen = cls._get_image_from_window()
702
+ next(gen)
703
+ return gen.send(window)
704
+
650
705
 
651
706
  class VideoWriter:
652
707
  def __init__(self, p, fourcc=None, width=None, height=None, fps=30):
@@ -957,6 +1012,63 @@ class Screen(_IVideo):
957
1012
  self._capture = False
958
1013
 
959
1014
 
1015
+ class WindowStream(_IVideo):
1016
+
1017
+ def __init__(self, window: cj.Window, *args, fps=None, **kwargs):
1018
+ self._window = window
1019
+ self._fps = fps or 30
1020
+ self._total_frames = -1
1021
+ self._capture = True
1022
+ self._frames = self.__get_frame()
1023
+ self._width, self._height = self._window.size
1024
+
1025
+ def set_fps(self, fps: Union[int, float]) -> None:
1026
+ assert isinstance(fps, (int, float)), ValueError(f'{fps} value for fps is not valid. Send int or float.')
1027
+ self._fps = fps
1028
+
1029
+ @property
1030
+ def next_frame(self) -> Tuple[bool, Union[np.ndarray, None]]:
1031
+ return True, next(self._frames)
1032
+
1033
+ def __get_frame(self):
1034
+ with cj.TempDir() as tmp:
1035
+ while self._capture:
1036
+ p = tmp.path.join('frame.bmp')
1037
+ self._window.capture_image_bmp(p.path)
1038
+ yield Image(p.path)
1039
+
1040
+ @property
1041
+ def width(self) -> int:
1042
+ return self._window.size[0]
1043
+
1044
+ @property
1045
+ def height(self) -> int:
1046
+ return self._window.size[1]
1047
+
1048
+ @property
1049
+ def total_frames(self) -> int:
1050
+ return self._total_frames
1051
+
1052
+ @property
1053
+ def fps(self) -> Union[int, float]:
1054
+ return self._fps
1055
+
1056
+ @property
1057
+ def is_webcam(self) -> bool:
1058
+ return True
1059
+
1060
+ @property
1061
+ def is_stream(self) -> bool:
1062
+ return False
1063
+
1064
+ @property
1065
+ def is_opened(self) -> bool:
1066
+ return self._capture
1067
+
1068
+ def stop(self):
1069
+ self._capture = False
1070
+
1071
+
960
1072
  class Video:
961
1073
 
962
1074
  def __init__(self, *args, fps=None, frame_preprocess=None, **kwargs):
@@ -976,7 +1088,9 @@ class Video:
976
1088
 
977
1089
  def _build(self):
978
1090
  if len(self._args):
979
- if isinstance(self._args[0], str):
1091
+ if isinstance(self._args[0], cj.Window):
1092
+ self._cap = WindowStream(window=self._args[0], *self._args[1:], **self._kwargs)
1093
+ elif isinstance(self._args[0], str):
980
1094
  if self._args[0] == 'monitor':
981
1095
  self._cap = Screen()
982
1096
  elif cj.request.is_url(self._args[0]):
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: calango
3
- Version: 2.2.8
3
+ Version: 2.2.9
4
4
  Summary: It looks like calango
5
5
  Home-page: https://github.com/cereja-project/calango
6
6
  Author: Joab Leite
@@ -15,6 +15,17 @@ Requires-Dist: cereja
15
15
  Requires-Dist: opencv-python
16
16
  Requires-Dist: matplotlib
17
17
  Requires-Dist: numpy
18
+ Requires-Dist: scikit-learn
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: classifier
22
+ Dynamic: description
23
+ Dynamic: description-content-type
24
+ Dynamic: home-page
25
+ Dynamic: license-file
26
+ Dynamic: requires-dist
27
+ Dynamic: requires-python
28
+ Dynamic: summary
18
29
 
19
30
  # Calango Project
20
31
 
@@ -2,3 +2,4 @@ cereja
2
2
  opencv-python
3
3
  matplotlib
4
4
  numpy
5
+ scikit-learn
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes