class_docstr: Network, which estimates the canonical orientation of the given 32x32 patches, in radians.
  
  Zero angle points towards right. This is based on the original code from paper
  "Repeatability Is Not Enough: Learning Discriminative Affine Regions via Discriminability"".
  See :cite:`AffNet2018` for more details.
  
  Args:
      pretrained: Download and set pretrained weights to the model.
      eps: to avoid division by zero in atan2.
  
  Returns:
      Angle in radians.
  
  Shape:
      - Input: (B, 1, 32, 32)
      - Output: (B)
  
  Examples:
      >>> input = torch.rand(16, 1, 32, 32)
      >>> orinet = OriNet()
      >>> angle = orinet(input) # 16
class_docstr_tok: ["Network",",","which","estimates","the","canonical","orientation","of","the","given","32x32","patches",",","in","radians",".","Zero","angle","points","towards","right",".","This","is","based","on","the","original","code","from","paper","''","Repeatability","Is","Not","Enough",":","Learning","Discriminative","Affine","Regions","via","Discriminability","''","''",".","See",":","cite",":","`","AffNet2018","`","for","more","details",".","Args",":","pretrained",":","Download","and","set","pretrained","weights","to","the","model",".","eps",":","to","avoid","division","by","zero","in","atan2",".","Returns",":","Angle","in","radians",".","Shape",":","-","Input",":","(","B",",","1",",","32",",","32",")","-","Output",":","(","B",")","Examples",":",">",">",">","input","=","torch.rand","(","16",",","1",",","32",",","32",")",">",">",">","orinet","=","OriNet","(",")",">",">",">","angle","=","orinet","(","input",")","#","16"]
code: def __init__(
      self, pretrained: bool = False, eps: float = 1e-8
  ) -> None:
      super().__init__()
      self.features = nn.Sequential(
          nn.Conv2d(1, 16, kernel_size=3, padding=1, bias=False),
          nn.BatchNorm2d(16, affine=False),
          nn.ReLU(),
          nn.Conv2d(
              16, 16, kernel_size=3, stride=1, padding=1, bias=False
          ),
          nn.BatchNorm2d(16, affine=False),
          nn.ReLU(),
          nn.Conv2d(
              16, 32, kernel_size=3, stride=2, padding=1, bias=False
          ),
          nn.BatchNorm2d(32, affine=False),
          nn.ReLU(),
          nn.Conv2d(
              32, 32, kernel_size=3, stride=1, padding=1, bias=False
          ),
          nn.BatchNorm2d(32, affine=False),
          nn.ReLU(),
          nn.Conv2d(
              32, 64, kernel_size=3, stride=2, padding=1, bias=False
          ),
          nn.BatchNorm2d(64, affine=False),
          nn.ReLU(),
          nn.Conv2d(
              64, 64, kernel_size=3, stride=1, padding=1, bias=False
          ),
          nn.BatchNorm2d(64, affine=False),
          nn.ReLU(),
          nn.Dropout(0.25),
          nn.Conv2d(
              64, 2, kernel_size=8, stride=1, padding=1, bias=True
          ),
          nn.Tanh(),
          nn.AdaptiveAvgPool2d(1),
      )
      self.eps = eps
      # use torch.hub to load pretrained model
      if pretrained:
          pretrained_dict = torch.hub.load_state_dict_from_url(
              urls["orinet"], map_location=map_location_to_cpu
          )
          self.load_state_dict(
              pretrained_dict["state_dict"], strict=False
          )
      self.eval()
  
imports: from typing import Dict, Optional
  import torch
  import torch.nn.functional
  from torch import nn
  from kornia.constants import pi
  from kornia.core.check import KORNIA_CHECK_LAF, KORNIA_CHECK_SHAPE
  from kornia.filters import SpatialGradient, get_gaussian_discrete_kernel1d, get_gaussian_kernel2d
  from kornia.geometry import rad2deg
  from kornia.utils.helpers import map_location_to_cpu
  from .laf import extract_patches_from_pyramid, get_laf_orientation, set_laf_orientation
label_desc: Use image node_id 1 to create a new OriNet object from inherited base classes: nn with example: obj = OriNet(pretrained, eps)