NumPy
lastmod 2025-02-18created 2015-12-1772 edits
NumPy (pronounced "num-pie") is a Python library that makes it easy to work with matrices and, more generally, large multidimensional arrays. Besides data structures, NumPy provides efficiently implemented functions for numerical computation.
Categories
- NumPy:Typing
- NumPy:Indexing (Fancy indexing - seems to be what the community calls it)
- NumPy:Broadcasting
Examples
Libraries
- msgpack-numpy - Serializes numpy objects with msgpack.
NumPy APIs
- numpy
- numpy.reshape - Change dimensions (shape)
- numpy.expand_dims - Add a dimension (e.g.
np.expand_dims(a, axis=0)) - numpy.newaxis - Used to add a new axis. (e.g.
a[:, np.newaxis]) - numpy.arange - Similar effect to
rangein python (e.g.np.arange(24)) - numpy.astype - Used to change the
dtype. - numpy.argwhere - Returns a list of indices of Non-zero elements. (e.g.
np.argwhere(arr >= 1))
Array
1D and 2D arrays are created/used as follows.
import numpy as np
a = np.array([1, 2, 3]) # Create a rank 1 array
print type(a) # Prints "<type 'numpy.ndarray'>"
print a.shape # Prints "(3,)"
print a[0], a[1], a[2] # Prints "1 2 3"
b = np.array([[1,2,3],[4,5,6]]) # Create a rank 2 array
print b.shape # Prints "(2, 3)"
print b[0, 0], b[0, 1], b[1, 0] # Prints "1 2 4"
For reference, arrays can also be created in the following ways.
import numpy as np
a = np.zeros((2,2)) # Create an array of all zeros
b = np.ones((1,2)) # Create an array of all ones
c = np.full((2,2), 7) # Create a constant array
d = np.eye(2) # Create a 2x2 identity matrix
e = np.random.random((2,2)) # Create an array filled with random values
Total number of elements:
Return the indices of the elements that are non-zero:
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> a > 3
array([[False, False, False],
[ True, True, True],
[ True, True, True]])
>>> np.nonzero(a > 3)
(array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
Array slicing
Slicing can be done as follows.
import numpy as np
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = a[:2, 1:3]
# [[2 3]
# [6 7]]
row_r1 = a[1, :] # Rank 1 view of the second row of a: # Prints "[5 6 7 8] (4,)"
row_r2 = a[1:2, :] # Rank 2 view of the second row of a: # Prints "[[5 6 7 8]] (1, 4)"
col_r1 = a[:, 1] # Rank 1: [ 2, 6, 10]
col_r2 = a[:, 1:2] # Rank 2: [[ 2], [ 6], [10]]
Array Indexing
import numpy as np
a = np.array([[1,2], [3, 4], [5, 6]])
a[[0, 1, 0]] # [[1, 2], [3, 4], [1, 2]]
a[[0, 1, 0], [0, 1, 0]] # [1, 4, 1]
# a[[0, 1, 0], [0, 1]] # ERROR!
Zero-copy Buffer
That's exactly right. Zero-copy is the most common reason to use mmap. Another way to wrap a mmap with a NumPy array is to do this:
numpy.frombuffer seems usable too
Add axis
Adding a new axis of length 1 via Indexing:
Adding a new axis while repeating the array:
Finding max/min
>>> import numpy as np
>>> n1 = np.array([[0,0,1,2,3],
... [5,6,7,0,0]])
>>> n1.max()
7
>>> n1.min()
0
>>> np.max(n1, axis=0)
array([5, 6, 7, 2, 3])
>>> np.max(n1, axis=1)
array([3, 7])
>>> np.min(n1, axis=0)
array([0, 0, 1, 0, 0])
>>> np.min(n1, axis=1)
array([0, 0])
min, max using the np.apply_along_axis function
Computes along the specified axis.
>>> import numpy as np
>>> n1 = np.array([[0,0,1,2,3],
... [5,6,7,0,0]])
>>> np.apply_along_axis(lambda a: np.min(a), 1, n1)
array([0, 0])
>>> np.apply_along_axis(lambda a: np.min(a), 0, n1)
array([0, 0, 1, 0, 0])
Getting the ROI Rect of a mask
import numpy as np
def find_roi(array):
# True 값을 가지는 좌표들을 찾습니다.
true_indices = np.argwhere(array)
# True 값이 없다면 ROI를 정의할 수 없습니다.
if true_indices.size == 0:
return None
# 좌표들의 최소값과 최대값을 찾습니다.
y_min, x_min = true_indices.min(axis=0)
y_max, x_max = true_indices.max(axis=0)
# ROI 좌표를 반환합니다. (x1, y1, x2, y2)
return x_min, y_min, x_max, y_max
# 예시 boolean 배열
arr = np.array([[0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0]])
roi = find_roi(arr)
print(f"ROI: {roi}")
Thoughts on the axis argument
import numpy as np
arr = np.array([[0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0]])
idx = np.argwhere(arr)
print(idx)
"""
array([[1, 2],
[1, 3],
[2, 2],
[2, 3],
[3, 2],
[3, 3],
[4, 2],
[4, 3]])
"""
-
idx.min()looks up the min value among all elements. -
idx.min(axis=0)-axis=0looks up the min value of each row. -
idx.min(axis=1)-axis=1looks up the min value of each column.
Read it like this (행 = row, 열 = column):
행1 행2
| |
array([[1, 2], - 열1
[1, 3], - 열2
[2, 2], - 열3
[2, 3], - 열4
[3, 2], - 열5
[3, 3], - 열6
[4, 2], - 열7
[4, 3]]) - 열8
- The result of
idx.min()is11. - The result of
idx.min(axis=0)isarray([1, 2]), since there are 2 rows. - The result of
idx.min(axis=1)isarray([1, 1, 2, 2, 2, 3, 2, 3]), since there are 8 rows.
In each case, you can see that one dimension is reduced.
Thoughts on the axis argument in 3D
import numpy as np
arr = np.array([[[1,4,3], [2,1,4]],
[[1,4,3], [3,1,4]],
[[4,3,2], [2,4,1]],
[[4,3,2], [3,4,1]]])
The shape is (4, 2, 3). That is, it is an image with H=4,W=2,C=3 (RGB).
In each case, you can see that one dimension is reduced.
-
idx.min(axis=0)-axis=0is H. With H removed it becomesW=2,C=3, and since the highest axis index is C, it finds the min value per C unit in H Steps. It finds the min value per C unit of each row. -
idx.min(axis=1)-axis=1is W. With W removed it becomesH=4,C=3, and since the highest axis index is C, it finds the min value per C unit in W Steps. It finds the min value per C unit of each column. -
idx.min(axis=2)-axis=2is C. With C removed it becomesH=4,W=2, and since the highest axis index is W, it finds the min value per W unit in H Steps. As a result, C is compressed. It becomes a GrayScale image.
The result of idx.min(axis=0):
C1 C2 C3 C4 C5 C6
/ / / / / /
array([[[1, 4, 3], [2, 1, 4]],
C1 C2 C3 C4 C5 C6
/ / / / / /
[[1, 4, 3], [3, 1, 4]],
C1 C2 C3 C4 C5 C6
/ / / / / /
[[4, 3, 2], [2, 4, 1]],
C1 C2 C3 C4 C5 C6
/ / / / / /
[[4, 3, 2], [3, 4, 1]]])
Grouping the same C{N} together gives array([[1, 3, 2], [2, 1, 1]]).
The result of idx.min(axis=1) (묶음 = group):
C1 C2 C3
/ / /
array([[[1, 4, 3],
[2, 1, 4]], ~ W1 묶음
\ \ \
C1 C2 C3
C1 C2 C3
/ / /
[[1, 4, 3],
[3, 1, 4]], ~ W2 묶음
\ \ \
C1 C2 C3
C1 C2 C3
/ / /
[[4, 3, 2],
[2, 4, 1]], ~ W3 묶음
\ \ \
C1 C2 C3
C1 C2 C3
/ / /
[[4, 3, 2],
[3, 4, 1]]]) ~ W4 묶음
\ \ \
C1 C2 C3
Grouping C{N} together within each W{N} gives array([[1, 1, 3], [1, 1, 3], [2, 3, 1], [3, 3, 1]]).
The result of idx.min(axis=2):
array([[[1, 4, 3], ~ W1
[2, 1, 4]], ~ W2
[[1, 4, 3], ~ W3
[3, 1, 4]], ~ W4
[[4, 3, 2], ~ W5
[2, 4, 1]], ~ W6
[[4, 3, 2], ~ W7
[3, 4, 1]]]) ~ W8
Grouping each W{N} gives array([[1, 1], [1, 1], [2, 1], [2, 1]]).
Datatypes
import numpy as np
x = np.array([1, 2])
print x.dtype # Prints "int64"
x = np.array([1, 2], dtype=np.int64) # Force a particular datatype
print x.dtype # Prints "int64"
Random data
Random colors
# load the class label names
CLASSES = open(args["classes"]).read().strip().split("\n")
# if a colors file was supplied, load it from disk
if args["colors"]:
COLORS = open(args["colors"]).read().strip().split("\n")
COLORS = [np.array(c.split(",")).astype("int") for c in COLORS]
COLORS = np.array(COLORS, dtype="uint8")
# otherwise, we need to randomly generate RGB colors for each class
# label
else:
# initialize a list of colors to represent each class label in
# the mask (starting with 'black' for the background/unlabeled
# regions)
np.random.seed(42)
COLORS = np.random.randint(0, 255, size=(len(CLASSES) - 1, 3),
dtype="uint8")
COLORS = np.vstack([[0, 0, 0], COLORS]).astype("uint8")
RGB888 image filled with a specific color
import numpy as np
def make_rgb888(width: int, height: int, r=0, g=0, b=0) -> np.ndarray:
return np.full(
shape=(height, width, 3),
fill_value=(r, g, b),
dtype=np.int8,
)
Valid RGB888 Image
from numpy import ndarray
DTYPE_KIND_BOOLEAN = "b"
DTYPE_KIND_SIGNED_INTEGER = "i"
DTYPE_KIND_UNSIGNED_INTEGER = "u"
DTYPE_KIND_FLOATING_POINT = "f"
DTYPE_KIND_COMPLEX_FLOATING_POINT = "c"
DTYPE_KIND_TIMEDELTA = "m"
DTYPE_KIND_DATETIME = "M"
DTYPE_KIND_OBJECT = "O"
DTYPE_KIND_BYTE_STRING = "S"
DTYPE_KIND_UNICODE = "U"
DTYPE_KIND_VOID = "V"
def valid_rgb888(image: ndarray) -> None:
dimension = len(image.shape)
if dimension != 3:
raise ValueError(f"The `shape` of `image` must be 3. (vs {dimension})")
h, w, c = image.shape
assert h >= 1
assert w >= 1
assert c >= 1
if c != 3:
raise ValueError(f"The `channel` must be 3. (vs {c})")
kind = image.dtype.kind
if kind not in [DTYPE_KIND_SIGNED_INTEGER, DTYPE_KIND_UNSIGNED_INTEGER]:
raise ValueError(
f"The `kind` must be '{DTYPE_KIND_SIGNED_INTEGER}'"
f" or '{DTYPE_KIND_UNSIGNED_INTEGER}'. (vs {kind})"
)
item_size = image.dtype.itemsize
if item_size != 1:
raise ValueError(f"The `item-size` must be 1. (vs {item_size})")
Creating a 1-channel mask from a 3-channel image using a color key
from typing import Final, Optional, Tuple
from numpy import concatenate, ndarray, uint8, where
from numpy.typing import NDArray
BLACK_COLOR: Final[Tuple[int, int, int]] = (0, 0, 0)
DEFAULT_CHROMA_COLOR: Final[Tuple[int, int, int]] = BLACK_COLOR
CHANNEL_MIN: Final[int] = 0
CHANNEL_MAX: Final[int] = 255
def generate_mask(
image: NDArray[uint8],
chroma_color=DEFAULT_CHROMA_COLOR,
) -> NDArray[uint8]:
assert image.dtype == uint8
assert len(image.shape) == 3
assert image.shape[-1] == 3
channels_cmp: NDArray[bool] = image == chroma_color
pixel_cmp: NDArray[bool] = channels_cmp.all(axis=-1, keepdims=True)
return where(pixel_cmp, CHANNEL_MIN, CHANNEL_MAX)
Merging a 3-channel image and a 1-channel mask into a 4-channel (BGRA) image
from typing import Final, Optional, Tuple
from numpy import concatenate, ndarray, uint8, where
from numpy.typing import NDArray
def merge_to_bgra32(image: NDArray[uint8], mask: NDArray[uint8]) -> NDArray[uint8]:
assert image.dtype == uint8
assert len(image.shape) == 3
assert image.shape[-1] == 3
assert mask.dtype == uint8
assert len(mask.shape) == 3
assert mask.shape[-1] == 1
return concatenate((image, mask), axis=-1)
Boolean array indexing
import numpy as np
a = np.array([[1,2], [3, 4], [5, 6]])
bool_idx = (a > 2) # [[False, False], [ True, True], [ True, True]]
bool_idx.dtype # bool
Select all non-black pixels in a NumPy array
You should use np.any instead of np.all for the second case of selecting all but black pixels:
Or simply get a complement of black pixels by inverting a boolean array by ~:
Working example:
import numpy as np
import matplotlib.pyplot as plt
image = plt.imread('example.png')
plt.imshow(image)
plt.show()
image_copy = image.copy()
black_pixels_mask = np.all(image == [0, 0, 0], axis=-1)
non_black_pixels_mask = np.any(image != [0, 0, 0], axis=-1)
# or non_black_pixels_mask = ~black_pixels_mask
image_copy[black_pixels_mask] = [255, 255, 255]
image_copy[non_black_pixels_mask] = [0, 0, 0]
plt.imshow(image_copy)
plt.show()
Reversing image RGB/BGR order
Conversion between any/all of BGR, RGB, and GBR may be necessary when working with
- Matplotlib
pyplot.imshow(): M x N x 3 image, where last dimension is RGB. - OpenCV
imshow(): M x N x 3 image, where last dimension is BGR - Scientific Cameras: some output M X N x 3 image, where last dimension is GBR
- BGR to RGB - OpenCV image to Matplotlib
-
rgb = bgr[...,::-1].copy()
- RGB to BGR - Matplotlib image to OpenCV
-
bgr = rgb[...,::-1].copy()
- RGB to GBR
-
gbr = rgb[...,[2,0,1]].copy()
The axis order convention for Python images:
- 3-D: W x H x 3, where the last axis is color (e.g. RGB)
- 4-D: W x H x 3 x 1, where the last axis is typically an alpha channel
How to convert an image to Grayscale
Create a random 2x3 RGB image:
import numpy as np
width = 2
height = 3
bgr_image = np.random.randint(0, 256, (height, width, 3), dtype=np.uint8)
bgr_image
Result:
array([[[177, 140, 52],
[ 35, 179, 111]],
[[149, 196, 241],
[ 0, 64, 236]],
[[188, 246, 74],
[185, 129, 10]]], dtype=uint8)
Create a 1-channel Grayscale image using mean:
Result:
Using np.stack, stack (bgr_image.mean(axis=2),) * 3 on the channel axis (axis=2; axis=-1 gives the same result):
Result:
array([[[123, 123, 123],
[108, 108, 108]],
[[195, 195, 195],
[100, 100, 100]],
[[169, 169, 169],
[108, 108, 108]]], dtype=uint8)
Serialize and Deserialize
import numpy as np
as_array = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
array_data_type = as_array.dtype.name
array_shape = as_array.shape
as_bytes = as_array.tobytes()
result = np.frombuffer(as_bytes, dtype = array_data_type).reshape(array_shape)
stack
Joins a sequence of arrays along a new axis.
The axis parameter specifies the index of the new axis in the dimensions of the result. For example, if axis=0 it will be the first dimension and if axis=-1 it will be the last dimension:
>>> import numpy as np
>>> a = np.array([[1, 2], [3, 4]])
>>> b = np.array([[5, 6], [7, 8]])
>>> np.stack([a, b])
array([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
Example
import numpy as np
## ..
print x + y
print np.add(x, y)
print x - y
print np.subtract(x, y)
print x * y
print np.multiply(x, y)
print x / y
print np.divide(x, y)
print np.sqrt(x)
## 내적은 dot을 사용한다.
print v.dot(w)
print np.dot(v, w)
## 총 합은 아래와 같이 구한다.
x = np.array([[1,2],[3,4]])
print np.sum(x) # Compute sum of all elements; prints "10"
print np.sum(x, axis=0) # Compute sum of each column; prints "[4 6]"
print np.sum(x, axis=1) # Compute sum of each row; prints "[3 7]"
## 랭크(Rank)를 뒤집는 방법은 아래와 같다.
x = np.array([[1,2], [3,4]])
print x.T # Prints "[[1 3], [2 4]]"
## 동일한 크기의 배열을 만들고자 할 때.
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
y = np.empty_like(x)
## 하나의 특정 값(또는 행렬)을 사용하여 반복적으로 적용하여, 또 다른 하나의 행렬을 만든다.
v = np.array([1, 0, 1])
vv = np.tile(v, (4, 1))
Numpy generate data from linear function
You can draw random data in the form of a linear function.
Np.random.uniform_-_example.png
Mean, variance, standard deviation
Multidimensional mean
Reducing dimensions (flattening; flatten)
from numpy import array
a = array([[1], [2], [3]])
a.flatten()
print(a.flatten())
## Output: "[1 2 3]"
Readonly (Lock; Freeze)
import numpy as np
a = np.zeros(11)
print("Before any change ")
print(a)
a[1] = 2
print("Before after first change ")
print(a)
a.setflags(write=False)
print("After making array immutable on attempting second change ")
a[1] = 7
Image processing with numpy
Type Hint
- Stackoverflow - Type hinting / annotation (PEP 484) for numpy.ndarray
- Type hinting / annotation (PEP 484) for ndarray, dtype, and ufunc #7370
- Using a library: nptyping - Type hints for Numpy
- Typing (numpy.typing) — NumPy v1.22.dev0 Manual
from typing import TypeVar, Generic, Tuple, Union, Optional
import numpy as np
Shape = TypeVar("Shape")
DType = TypeVar("DType")
class Array(np.ndarray, Generic[Shape, DType]):
"""
Use this to type-annotate numpy arrays, e.g.
def transform_image(image: Array['H,W,3', np.uint8], ...):
...
"""
pass
def func(arr: Array['N,2', int]):
return arr*2
print(func(arr = np.array([(1, 2), (3, 4)])))
C Extension
- [Recommended] How to extend NumPy
- Stackoverflow: Pointer-type mismatch with PyArray_SimpleNew
- Numpy - C (Simple example)
Required
You must call the function below before calling any NumPy-related functions.
NumPy style arrays for C++
Here are several free software that may suit your needs.
- The GNU Scientific Library is a GPL software written in C. Thus, it has a C-like allocation and way of programming (pointers, etc.). With the GSLwrap, you can have a C++ way of programming, while still using the GSL. GSL has a BLAS implementation, but you can use ATLAS instead of the default CBLAS, if you want even more performances.
- The boost/uBLAS library is a BSL library, written in C++ and distributed as a boost package. It is a C++-way of implementing the BLAS standard. uBLAS comes with a few linear algebra functions, and there is an experimental binding to ATLAS.
- eigen is a linear algebra library written in C++, distributed under the LGPL3 (or GPL2). It's a C++ way of programming, but more integrated than the two others (more algorithms and data structures are available). Eigen claim to be faster than the BLAS implementations above, while not following the de-facto standard BLAS API. Eigen does not seem to put a lot of effort on parallel implementation.
- Armadillo is LGPL3 library for C++. It has binding for LAPACK (the library used by numpy). It uses recursive templates and template meta-programming, which is a good point (I don't know if other libraries are doing it also?).
- xtensor is a C++ library that is BSD licensed. It offers A C++ API very similar to that of NumPy. See https://xtensor.readthedocs.io/en/latest/numpy.html for a cheat sheet.
These alternatives are really good if you just want to get data structures and basic linear algebra. Depending on your taste about style, license or sysadmin challenges (installing big libraries like LAPACK may be difficult), you may choose the one that best suits your needs.
Troubleshooting
ValueError: numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject
The following error occurred while using something like PandasAI:
Traceback (most recent call last):
File "/home/yourid/Project/steel-reports/main.py", line 16, in <module>
sys.exit(main())
File "/home/yourid/Project/steel-reports/steelreports/entrypoint.py", line 60, in main
return run_default_app(*files, debug=debug, verbose=verbose)
File "/home/yourid/Project/steel-reports/steelreports/apps/__init__.py", line 7, in run_default_app
from steelreports.apps.default import DefaultApp
File "/home/yourid/Project/steel-reports/steelreports/apps/default.py", line 3, in <module>
from pandasai import SmartDataframe
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandasai/__init__.py", line 6, in <module>
from pandasai.smart_dataframe import SmartDataframe
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandasai/smart_dataframe/__init__.py", line 26, in <module>
import pandasai.pandas as pd
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandasai/pandas/__init__.py", line 13, in <module>
from pandas import *
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandas/__init__.py", line 22, in <module>
from pandas.compat import is_numpy_dev as _is_numpy_dev # pyright: ignore # noqa:F401
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandas/compat/__init__.py", line 18, in <module>
from pandas.compat.numpy import (
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandas/compat/numpy/__init__.py", line 4, in <module>
from pandas.util.version import Version
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandas/util/__init__.py", line 2, in <module>
from pandas.util._decorators import ( # noqa:F401
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandas/util/_decorators.py", line 14, in <module>
from pandas._libs.properties import cache_readonly
File "/home/yourid/Project/steel-reports/.venv/lib/python3.9/site-packages/pandas/_libs/__init__.py", line 13, in <module>
from pandas._libs.interval import Interval
File "pandas/_libs/interval.pyx", line 1, in init pandas._libs.interval
ValueError: numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject
It's a numpy version problem. If you're using 2.xx, downgrade to 1.xx. (As of 2024-12-03, numpy=1.26.4 is the latest)
See also
- Python
- CPython
- SciPy
- matplotlib
- BLAS
- Bolt - A 10x faster matrix & vector operation algorithm
- pandas
- scikit-learn
Favorite site
- Python Numpy Tutorial
- [Recommended] Python Data Science Cheat Sheet: NumPy basics, fundamentals 1
- Cookbook/Indexing - SciPy wiki dump
References
-
Taewan.kim_-_numpy_cheat_sheet.pdf ↩
- 3DSegmentation:Basic
- Angle
- Bolt
- Caffe
- Caffe:Install
- Computer Language
- CPython
- CuPy
- Curriculum
- Cv::Mat:Python
- Deep learning
- Geophyte
- Im2col
- KlongPy
- Linear regression
- Machine learning
- MachineLearning:Course:Python
- MaskRCNN:Example:VideoReadWrite
- Matplotlib
- MessagePack
- Msgpack-numpy
- Numba
- Numpy.argwhere
- NumPy:Broadcasting
- NumPy:Indexing
- NumPy:Typing
- Open Neural Network Exchange
- OpenCV
- OpenCV:Basic
- OpenCV:Example:CropCenter
- PandasAI
- Pillow
- PyScript
- Python Imaging Library
- Python:Ellipsis
- Python:Isolation
- Python:Libraries
- Python:multiprocessing.shared memory
- Scikit-learn
- SciPy
- Scripting Language
- Seaborn
- Statsmodels
- SymPy
- Tinyvector
- Vector