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 ..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(
65        self,
66        run_config: BarcodeEngineRunConfig,
67        rng: Optional[RandomGenerator] = None,
68    ) -> ScoreMap:
69        assert rng is not None
70
71        payload_text_length = rng.integers(
72            self.init_config.payload_text_length_min,
73            self.init_config.payload_text_length_max + 1,
74        )
75        payload_text = ''.join(
76            rng_choice_with_size(rng, self.ascii_letters, size=payload_text_length)
77        )
78
79        qrcode_encoder = cv.QRCodeEncoder.create()
80        # Black as activated pixels.
81        mask = Mask(mat=qrcode_encoder.encode(payload_text)).to_inverted_mask()
82        assert mask.height == mask.width
83
84        qrcode_score_map = ScoreMap.from_shapable(mask)
85        qrcode_score_map[mask] = float(
86            rng.uniform(self.init_config.alpha_min, self.init_config.alpha_max)
87        )
88
89        if qrcode_score_map.shape != (run_config.height, run_config.width):
90            qrcode_score_map = qrcode_score_map.to_resized_score_map(
91                resized_height=run_config.height,
92                resized_width=run_config.width,
93            )
94
95        return qrcode_score_map
96
97
98barcode_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(
66        self,
67        run_config: BarcodeEngineRunConfig,
68        rng: Optional[RandomGenerator] = None,
69    ) -> ScoreMap:
70        assert rng is not None
71
72        payload_text_length = rng.integers(
73            self.init_config.payload_text_length_min,
74            self.init_config.payload_text_length_max + 1,
75        )
76        payload_text = ''.join(
77            rng_choice_with_size(rng, self.ascii_letters, size=payload_text_length)
78        )
79
80        qrcode_encoder = cv.QRCodeEncoder.create()
81        # Black as activated pixels.
82        mask = Mask(mat=qrcode_encoder.encode(payload_text)).to_inverted_mask()
83        assert mask.height == mask.width
84
85        qrcode_score_map = ScoreMap.from_shapable(mask)
86        qrcode_score_map[mask] = float(
87            rng.uniform(self.init_config.alpha_min, self.init_config.alpha_max)
88        )
89
90        if qrcode_score_map.shape != (run_config.height, run_config.width):
91            qrcode_score_map = qrcode_score_map.to_resized_score_map(
92                resized_height=run_config.height,
93                resized_width=run_config.width,
94            )
95
96        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: Union[numpy.random._generator.Generator, NoneType] = None) -> vkit.element.score_map.ScoreMap:
65    def run(
66        self,
67        run_config: BarcodeEngineRunConfig,
68        rng: Optional[RandomGenerator] = None,
69    ) -> ScoreMap:
70        assert rng is not None
71
72        payload_text_length = rng.integers(
73            self.init_config.payload_text_length_min,
74            self.init_config.payload_text_length_max + 1,
75        )
76        payload_text = ''.join(
77            rng_choice_with_size(rng, self.ascii_letters, size=payload_text_length)
78        )
79
80        qrcode_encoder = cv.QRCodeEncoder.create()
81        # Black as activated pixels.
82        mask = Mask(mat=qrcode_encoder.encode(payload_text)).to_inverted_mask()
83        assert mask.height == mask.width
84
85        qrcode_score_map = ScoreMap.from_shapable(mask)
86        qrcode_score_map[mask] = float(
87            rng.uniform(self.init_config.alpha_min, self.init_config.alpha_max)
88        )
89
90        if qrcode_score_map.shape != (run_config.height, run_config.width):
91            qrcode_score_map = qrcode_score_map.to_resized_score_map(
92                resized_height=run_config.height,
93                resized_width=run_config.width,
94            )
95
96        return qrcode_score_map