vkit.engine.barcode.qr

 1# Copyright 2022 vkit-x Administrator. All Rights Reserved.
 2#
 3# This project (vkit-x/vkit) is dual-licensed under commercial and SSPL licenses.
 4#
 5# The commercial license gives you the full rights to create and distribute software
 6# on your own terms without any SSPL license obligations. For more information,
 7# please see the "LICENSE_COMMERCIAL.txt" file.
 8#
 9# This project is also available under Server Side Public License (SSPL).
10# The SSPL licensing is ideal for use cases such as open source projects with
11# SSPL distribution, student/academic purposes, hobby projects, internal research
12# projects without external distribution, or other projects where all SSPL
13# obligations can be met. For more information, please see the "LICENSE_SSPL.txt" file.
14from typing import Optional
15import string
16
17import attrs
18from numpy.random import Generator as RandomGenerator
19import cv2 as cv
20
21from vkit.utility import rng_choice_with_size
22from vkit.element import Mask, ScoreMap
23from vkit.engine.interface import (
24    Engine,
25    EngineExecutorFactory,
26    NoneTypeEngineInitResource,
27)
28from .type import BarcodeEngineRunConfig
29
30CV_PAYLOAD_TEXT_LENGTH_MAX = 150
31
32
33@attrs.define
34class BarcodeQrEngineInitConfig:
35    payload_text_length_min: int = 1
36    payload_text_length_max: int = CV_PAYLOAD_TEXT_LENGTH_MAX
37    alpha_min: float = 0.7
38    alpha_max: float = 1.0
39
40
41class BarcodeQrEngine(
42    Engine[
43        BarcodeQrEngineInitConfig,
44        NoneTypeEngineInitResource,
45        BarcodeEngineRunConfig,
46        ScoreMap,
47    ]
48):  # yapf: disable
49
50    @classmethod
51    def get_type_name(cls) -> str:
52        return 'qr'
53
54    def __init__(
55        self,
56        init_config: BarcodeQrEngineInitConfig,
57        init_resource: Optional[NoneTypeEngineInitResource] = None,
58    ):
59        super().__init__(init_config, init_resource)
60
61        assert self.init_config.payload_text_length_max <= CV_PAYLOAD_TEXT_LENGTH_MAX
62        self.ascii_letters = tuple(string.ascii_letters)
63
64    def run(self, run_config: BarcodeEngineRunConfig, rng: RandomGenerator) -> ScoreMap:
65        payload_text_length = rng.integers(
66            self.init_config.payload_text_length_min,
67            self.init_config.payload_text_length_max + 1,
68        )
69        payload_text = ''.join(
70            rng_choice_with_size(rng, self.ascii_letters, size=payload_text_length)
71        )
72
73        qrcode_encoder = cv.QRCodeEncoder.create()
74        # Black as activated pixels.
75        mask = Mask(mat=qrcode_encoder.encode(payload_text)).to_inverted_mask()
76        assert mask.height == mask.width
77
78        qrcode_score_map = ScoreMap.from_shapable(mask)
79        qrcode_score_map[mask] = float(
80            rng.uniform(self.init_config.alpha_min, self.init_config.alpha_max)
81        )
82
83        if qrcode_score_map.shape != (run_config.height, run_config.width):
84            qrcode_score_map = qrcode_score_map.to_resized_score_map(
85                resized_height=run_config.height,
86                resized_width=run_config.width,
87            )
88
89        return qrcode_score_map
90
91
92barcode_qr_engine_executor_factory = EngineExecutorFactory(BarcodeQrEngine)
class BarcodeQrEngineInitConfig:
35class BarcodeQrEngineInitConfig:
36    payload_text_length_min: int = 1
37    payload_text_length_max: int = CV_PAYLOAD_TEXT_LENGTH_MAX
38    alpha_min: float = 0.7
39    alpha_max: float = 1.0
BarcodeQrEngineInitConfig( payload_text_length_min: int = 1, payload_text_length_max: int = 150, alpha_min: float = 0.7, alpha_max: float = 1.0)
2def __init__(self, payload_text_length_min=attr_dict['payload_text_length_min'].default, payload_text_length_max=attr_dict['payload_text_length_max'].default, alpha_min=attr_dict['alpha_min'].default, alpha_max=attr_dict['alpha_max'].default):
3    self.payload_text_length_min = payload_text_length_min
4    self.payload_text_length_max = payload_text_length_max
5    self.alpha_min = alpha_min
6    self.alpha_max = alpha_max

Method generated by attrs for class BarcodeQrEngineInitConfig.

42class BarcodeQrEngine(
43    Engine[
44        BarcodeQrEngineInitConfig,
45        NoneTypeEngineInitResource,
46        BarcodeEngineRunConfig,
47        ScoreMap,
48    ]
49):  # yapf: disable
50
51    @classmethod
52    def get_type_name(cls) -> str:
53        return 'qr'
54
55    def __init__(
56        self,
57        init_config: BarcodeQrEngineInitConfig,
58        init_resource: Optional[NoneTypeEngineInitResource] = None,
59    ):
60        super().__init__(init_config, init_resource)
61
62        assert self.init_config.payload_text_length_max <= CV_PAYLOAD_TEXT_LENGTH_MAX
63        self.ascii_letters = tuple(string.ascii_letters)
64
65    def run(self, run_config: BarcodeEngineRunConfig, rng: RandomGenerator) -> ScoreMap:
66        payload_text_length = rng.integers(
67            self.init_config.payload_text_length_min,
68            self.init_config.payload_text_length_max + 1,
69        )
70        payload_text = ''.join(
71            rng_choice_with_size(rng, self.ascii_letters, size=payload_text_length)
72        )
73
74        qrcode_encoder = cv.QRCodeEncoder.create()
75        # Black as activated pixels.
76        mask = Mask(mat=qrcode_encoder.encode(payload_text)).to_inverted_mask()
77        assert mask.height == mask.width
78
79        qrcode_score_map = ScoreMap.from_shapable(mask)
80        qrcode_score_map[mask] = float(
81            rng.uniform(self.init_config.alpha_min, self.init_config.alpha_max)
82        )
83
84        if qrcode_score_map.shape != (run_config.height, run_config.width):
85            qrcode_score_map = qrcode_score_map.to_resized_score_map(
86                resized_height=run_config.height,
87                resized_width=run_config.width,
88            )
89
90        return qrcode_score_map

Abstract base class for generic types.

A generic type is typically declared by inheriting from this class parameterized with one or more type variables. For example, a generic mapping type might be defined as::

class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.

This class can then be used as follows::

def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: try: return mapping[key] except KeyError: return default

BarcodeQrEngine( init_config: vkit.engine.barcode.qr.BarcodeQrEngineInitConfig, init_resource: Union[vkit.engine.interface.NoneTypeEngineInitResource, NoneType] = None)
55    def __init__(
56        self,
57        init_config: BarcodeQrEngineInitConfig,
58        init_resource: Optional[NoneTypeEngineInitResource] = None,
59    ):
60        super().__init__(init_config, init_resource)
61
62        assert self.init_config.payload_text_length_max <= CV_PAYLOAD_TEXT_LENGTH_MAX
63        self.ascii_letters = tuple(string.ascii_letters)
@classmethod
def get_type_name(cls) -> str:
51    @classmethod
52    def get_type_name(cls) -> str:
53        return 'qr'
def run( self, run_config: vkit.engine.barcode.type.BarcodeEngineRunConfig, rng: numpy.random._generator.Generator) -> vkit.element.score_map.ScoreMap:
65    def run(self, run_config: BarcodeEngineRunConfig, rng: RandomGenerator) -> ScoreMap:
66        payload_text_length = rng.integers(
67            self.init_config.payload_text_length_min,
68            self.init_config.payload_text_length_max + 1,
69        )
70        payload_text = ''.join(
71            rng_choice_with_size(rng, self.ascii_letters, size=payload_text_length)
72        )
73
74        qrcode_encoder = cv.QRCodeEncoder.create()
75        # Black as activated pixels.
76        mask = Mask(mat=qrcode_encoder.encode(payload_text)).to_inverted_mask()
77        assert mask.height == mask.width
78
79        qrcode_score_map = ScoreMap.from_shapable(mask)
80        qrcode_score_map[mask] = float(
81            rng.uniform(self.init_config.alpha_min, self.init_config.alpha_max)
82        )
83
84        if qrcode_score_map.shape != (run_config.height, run_config.width):
85            qrcode_score_map = qrcode_score_map.to_resized_score_map(
86                resized_height=run_config.height,
87                resized_width=run_config.width,
88            )
89
90        return qrcode_score_map