mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 07:13:02 +04:00
Merge pull request #28536 from Sikandar1310291:fix/inrange-typing-28534
Fix inRange type signature to accept Scalar values #28536 Fixes #28534 The Python type signature for cv2.inRange was too restrictive, requiring MatLike for lowerb and upperb parameters. However, the C++ implementation accepts InputArray which includes Scalar values (tuples, floats, etc.). This caused type checkers to incorrectly flag valid code from official tutorials as type errors. Added make_matlike_or_scalar_arg() refinement function to create union types MatLike | Scalar for affected parameters, matching the C++ InputArray behavior. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -8,7 +8,7 @@ from .nodes import (NamespaceNode, FunctionNode, OptionalTypeNode, TypeNode,
|
||||
ClassProperty, PrimitiveTypeNode, ASTNodeTypeNode,
|
||||
AggregatedTypeNode, CallableTypeNode, AnyTypeNode,
|
||||
TupleTypeNode, UnionTypeNode, ProtocolClassNode,
|
||||
DictTypeNode, ClassTypeNode)
|
||||
DictTypeNode, ClassTypeNode, AliasRefTypeNode)
|
||||
from .ast_utils import (find_function_node, SymbolName,
|
||||
for_each_function_overload)
|
||||
from .types_conversion import create_type_node
|
||||
@@ -376,6 +376,62 @@ def _find_argument_index(arguments: Sequence[FunctionNode.Arg],
|
||||
return None
|
||||
|
||||
|
||||
def make_matlike_or_scalar_arg(*arg_names: str) -> Callable[[NamespaceNode, SymbolName], None]:
|
||||
"""Make arguments accept both MatLike and Scalar types.
|
||||
|
||||
This is used for functions like inRange where the C++ InputArray parameter
|
||||
can accept both Mat objects and Scalar values (tuples, floats, etc.).
|
||||
|
||||
Example: cv2.inRange(img, (0, 0, 0), (255, 255, 255)) should be valid.
|
||||
"""
|
||||
def _make_matlike_or_scalar_arg(root_node: NamespaceNode,
|
||||
function_symbol_name: SymbolName) -> None:
|
||||
from .predefined_types import PREDEFINED_TYPES
|
||||
|
||||
function = find_function_node(root_node, function_symbol_name)
|
||||
for arg_name in arg_names:
|
||||
found_overload_with_arg = False
|
||||
|
||||
for overload in function.overloads:
|
||||
arg_idx = _find_argument_index(overload.arguments, arg_name)
|
||||
|
||||
# skip overloads without this argument
|
||||
if arg_idx is None:
|
||||
continue
|
||||
|
||||
current_type = overload.arguments[arg_idx].type_node
|
||||
|
||||
# Check if it's already a union or if it already includes Scalar
|
||||
if isinstance(current_type, UnionTypeNode):
|
||||
# Check if Scalar is already in the union
|
||||
has_scalar = any(
|
||||
isinstance(item, AliasRefTypeNode) and item.typename == "Scalar"
|
||||
for item in current_type.items
|
||||
)
|
||||
if has_scalar:
|
||||
continue
|
||||
# Add Scalar to existing union
|
||||
scalar_ref = AliasRefTypeNode("Scalar")
|
||||
current_type.items = current_type.items + (scalar_ref,)
|
||||
else:
|
||||
# Create a union of current type and Scalar
|
||||
scalar_ref = AliasRefTypeNode("Scalar")
|
||||
overload.arguments[arg_idx].type_node = UnionTypeNode(
|
||||
f"{arg_name}_type",
|
||||
(cast(TypeNode, current_type), scalar_ref)
|
||||
)
|
||||
|
||||
found_overload_with_arg = True
|
||||
|
||||
if not found_overload_with_arg:
|
||||
raise RuntimeError(
|
||||
f"Failed to find argument with name: '{arg_name}'"
|
||||
f" in '{function_symbol_name.name}' overloads"
|
||||
)
|
||||
|
||||
return _make_matlike_or_scalar_arg
|
||||
|
||||
|
||||
NODES_TO_REFINE = {
|
||||
SymbolName(("cv", ), (), "resize"): make_optional_arg("dsize"),
|
||||
SymbolName(("cv", ), (), "calcHist"): make_optional_arg("mask"),
|
||||
@@ -401,6 +457,8 @@ NODES_TO_REFINE = {
|
||||
SymbolName(("cv", "fisheye"), (), "initUndistortRectifyMap"): make_optional_arg("D"),
|
||||
SymbolName(("cv", ), (), "imread"): make_optional_none_return,
|
||||
SymbolName(("cv", ), (), "imdecode"): make_optional_none_return,
|
||||
# Fix for issue #28534: inRange should accept Scalar for lowerb and upperb
|
||||
SymbolName(("cv", ), (), "inRange"): make_matlike_or_scalar_arg("lowerb", "upperb"),
|
||||
}
|
||||
|
||||
ERROR_CLASS_PROPERTIES = (
|
||||
|
||||
Reference in New Issue
Block a user