LogoXpertNet: a novel lightweight logo classification using deep learning.
The 11 matches
- [1] § Methodology › Proposed LogoXpertNet for logo classification › Modified MobileNetv3 for feature extraction ↔ LogoXpertNet Model.py, lines 30 to 60 · score 0.80 · depthwise separable convolutions, pointwise convolution, Bottleneck Block, MobileNetV3, channel · Report a mismatch
- [2] § Methodology › Proposed LogoXpertNet for logo classification ↔ LogoXpertNet Model.py, lines 265 to 344 · score 0.73 · refined feature map, frequency domain, channel attention, FA CBAM, DCT, augmentation · Report a mismatch
- [3] § Methodology › Proposed LogoXpertNet for logo classification › Proposed hierarchical squeeze-excitation spatial attention block (HSE-SAB) ↔ LogoXpertNet Model.py, lines 199 to 260 · score 0.72 · concatenated pooled features, Hierarchical channel, modulates, ReLU, feature map, sigmoid · Report a mismatch
- [4] § Methodology › Proposed LogoXpertNet for logo classification › Proposed hierarchical squeeze-excitation spatial attention block (HSE-SAB) ↔ LogoXpertNet Model.py, lines 199 to 260 · score 0.71 · Hierarchical Squeeze Excitation, hierarchical channel, Spatial Attention Block, HSE SAB, dynamically, dimensions · Report a mismatch
- [5] § Methodology › Proposed LogoXpertNet for logo classification › Proposed feature aware convolution block attention module ↔ LogoXpertNet Model.py, lines 265 to 344 · score 0.70 · ReLU, max pooling, Channel attention, FA CBAM, feature map, sigmoid · Report a mismatch
- [6] § Methodology › Proposed LogoXpertNet for logo classification ↔ LogoXpertNet Model.py, lines 349 to 482 · score 0.66 · HSE SAB module, CLFF module, FA CBAM, LogoXpertNet, deep, layer · Report a mismatch
- [7] § Methodology › Proposed LogoXpertNet for logo classification › Modified MobileNetv3 for feature extraction ↔ LogoXpertNet Model.py, lines 30 to 60 · score 0.65 · depthwise separable convolutions, Bottleneck Block, MobileNetV3 · Report a mismatch
- [8] § Methodology › Proposed LogoXpertNet for logo classification › Proposed feature aware convolution block attention module ↔ LogoXpertNet Model.py, lines 10 to 20 · score 0.61 · Discrete Cosine Transform, FFT, DCT · Report a mismatch
- [9] § Methodology › Proposed LogoXpertNet for logo classification › Cross-layer feature fusion (CLFF) module ↔ LogoXpertNet Model.py, lines 137 to 194 · score 0.57 · Cross Layer Feature, deep layers, recalibration, feature map, CLFF, Fusion · Report a mismatch
- [10] § Methodology › Proposed LogoXpertNet for logo classification › Cross-layer feature fusion (CLFF) module ↔ LogoXpertNet Model.py, lines 137 to 194 · score 0.56 · recalibrated feature map, cross layer feature, fusion, CLFF, module · Report a mismatch
- [11] § Methodology › Proposed LogoXpertNet for logo classification ↔ LogoXpertNet Model.py, lines 10 to 20 · score 0.51 · Discrete Cosine Transform, DCT · Report a mismatch
Paper
Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 574 lines · 21 KB · no license · 11 matches
- import torch
- import torch.nn as nn
- import torch.nn.functional as F
- import numpy as np
- from torchvision.models import mobilenet_v3_small, MobileNet_V3_Small_Weights
- from typing import Optional, Tuple
- # ==================== Helper Functions ====================
- def dct2d(x: torch.Tensor) -> torch.Tensor:
- """
- Discrete Cosine Transform (DCT) implementation using FFT
- Approximation as mentioned in the paper
- """
- N, C, H, W = x.shape
- # Using real part of FFT as approximation of DCT
- x_padded = F.pad(x, (0, 0, 0, 0)) # No padding for now
- fft_result = torch.fft.fft2(x_padded, dim=(-2, -1))
- dct_result = torch.real(fft_result)
- return dct_result
- def local_avg_pool(x: torch.Tensor, kernel_size: int = 3, stride: int = 1) -> torch.Tensor:
- """
- Local Average Pooling for HSE-SAB
- """
- return F.avg_pool2d(x, kernel_size=kernel_size, stride=stride, padding=kernel_size//2)
- # ==================== Modified MobileNetV3 Backbone ====================
- class BottleneckBlock(nn.Module):
- """
- Bottleneck Block from MobileNetV3 with depthwise separable convolutions
- """
- def __init__(self, in_channels: int, out_channels: int, stride: int = 1, expansion_factor: int = 6):
- super().__init__()
- hidden_channels = in_channels * expansion_factor
- self.conv = nn.Sequential(
- # Pointwise convolution
- nn.Conv2d(in_channels, hidden_channels, 1, 1, 0, bias=False),
- nn.BatchNorm2d(hidden_channels),
- nn.ReLU6(inplace=True),
- # Depthwise convolution
- nn.Conv2d(hidden_channels, hidden_channels, 3, stride, 1,
- groups=hidden_channels, bias=False),
- nn.BatchNorm2d(hidden_channels),
- nn.ReLU6(inplace=True),
- # Pointwise convolution (linear)
- nn.Conv2d(hidden_channels, out_channels, 1, 1, 0, bias=False),
- nn.BatchNorm2d(out_channels)
- )
- self.use_residual = (stride == 1 and in_channels == out_channels)
- def forward(self, x: torch.Tensor) -> torch.Tensor:
- if self.use_residual:
- return x + self.conv(x)
- return self.conv(x)
- class ModifiedMobileNetV3(nn.Module):
- """
- Modified MobileNetV3 backbone with Bottleneck and CLFF blocks integrated
- """
- def __init__(self, num_classes: int = 1000, pretrained: bool = False):
- super().__init__()
- # Load pretrained MobileNetV3 Small
- weights = MobileNet_V3_Small_Weights.DEFAULT if pretrained else None
- backbone = mobilenet_v3_small(weights=weights)
- # Extract features
- self.features = backbone.features
- # Remove the last classification layer
- self.features = nn.Sequential(*list(self.features.children()))
- # Modify with Bottleneck blocks at specific layers
- self._modify_with_bottleneck()
- # Adaptive pooling
- self.avgpool = nn.AdaptiveAvgPool2d(1)
- # Store feature dimensions for CLFF
- self.feature_dims = {
- 'early': 24, # After layer 2 (adjust based on actual architecture)
- 'deep': 576 # Final feature dimension
- }
- def _modify_with_bottleneck(self):
- """
- Replace some convolution blocks with Bottleneck blocks
- """
- # Convert sequential to list for modification
- layers = list(self.features.children())
- # Replace certain layers with Bottleneck blocks
- # In practice, you'd replace specific conv blocks based on paper details
- # This is a simplified implementation
- for i in range(len(layers)):
- if isinstance(layers[i], nn.Conv2d) and layers[i].kernel_size == (3, 3):
- in_channels = layers[i].in_channels
- out_channels = layers[i].out_channels
- stride = layers[i].stride[0]
- # Create bottleneck block
- bottleneck = BottleneckBlock(in_channels, out_channels, stride)
- layers[i] = bottleneck
- self.features = nn.Sequential(*layers)
- def forward(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
- """
- Returns both early and deep layer features for CLFF
- """
- # Extract early features (after 2nd block)
- early_feat = None
- for i, layer in enumerate(self.features):
- x = layer(x)
- if i == 2: # After second layer
- early_feat = x
- # Deep features (final output)
- deep_feat = x
- # Global pooling
- deep_feat = self.avgpool(deep_feat)
- deep_feat = torch.flatten(deep_feat, 1)
- return early_feat, deep_feat
- # ==================== CLFF Module ====================
- class CLFF(nn.Module):
- """
- Cross-Layer Feature Fusion Module
- """
- def __init__(self, early_channels: int, deep_channels: int,
- fusion_method: str = 'concat'):
- super().__init__()
- self.fusion_method = fusion_method
- # Squeeze-Excitation layers
- total_channels = early_channels + deep_channels if fusion_method == 'concat' else early_channels
- self.squeeze = nn.AdaptiveAvgPool2d(1)
- # Excitation with two FC layers
- reduction_ratio = 16
- reduced_channels = max(total_channels // reduction_ratio, 4)
- self.excitation = nn.Sequential(
- nn.Linear(total_channels, reduced_channels, bias=False),
- nn.ReLU(inplace=True),
- nn.Linear(reduced_channels, total_channels, bias=False),
- nn.Sigmoid()
- )
- def forward(self, F1: torch.Tensor, F2: torch.Tensor) -> torch.Tensor:
- """
- Args:
- F1: Early layer feature map [B, C1, H, W]
- F2: Deep layer feature map [B, C2, H, W]
- Returns:
- Recalibrated feature map
- """
- # Step 1: Feature Fusion
- if self.fusion_method == 'concat':
- F_fusion = torch.cat([F1, F2], dim=1) # [B, C1+C2, H, W]
- elif self.fusion_method == 'add':
- # Ensure same dimensions for addition
- if F1.shape != F2.shape:
- F2_resized = F.interpolate(F2, size=F1.shape[-2:], mode='bilinear', align_corners=False)
- F_fusion = F1 + F2_resized
- else:
- F_fusion = F1 + F2
- else:
- raise ValueError(f"Unknown fusion method: {self.fusion_method}")
- # Step 2: Squeeze Operation (Global Average Pooling)
- z = self.squeeze(F_fusion) # [B, C, 1, 1]
- z = z.flatten(1) # [B, C]
- # Step 3: Excitation Operation
- a = self.excitation(z) # [B, C]
- a = a.view(a.shape[0], a.shape[1], 1, 1) # [B, C, 1, 1]
- # Step 4: Recalibration
- F_out = F_fusion * a.expand_as(F_fusion)
- return F_out
- # ==================== HSE-SAB Module ====================
- class HSE_SAB(nn.Module):
- """
- Hierarchical Squeeze-Excitation Spatial Attention Block
- """
- def __init__(self, in_channels: int, reduction_ratio: int = 16,
- local_pool_size: int = 3):
- super().__init__()
- self.in_channels = in_channels
- # Multi-scale pooling
- self.global_avg_pool = nn.AdaptiveAvgPool2d(1)
- self.global_max_pool = nn.AdaptiveMaxPool2d(1)
- self.local_avg_pool = lambda x: local_avg_pool(x, kernel_size=local_pool_size)
- # Hierarchical channel-wise excitation
- reduced_channels = max(in_channels // reduction_ratio, 4)
- # Since we concatenate pooled features, input to FC will have more channels
- # We'll handle dynamic dimensions in forward pass
- self.fc1 = nn.Linear(in_channels * 3, reduced_channels) # 3 for avg, max, local
- self.fc2 = nn.Linear(reduced_channels, in_channels)
- # Spatial attention
- self.spatial_conv = nn.Conv2d(in_channels, 1, kernel_size=1)
- def forward(self, x: torch.Tensor) -> torch.Tensor:
- """
- Args:
- x: Input feature map [B, C, H, W]
- Returns:
- Refined feature map [B, C, H, W]
- """
- B, C, H, W = x.shape
- # Step 1: Multi-Scale Pooling
- F_avg = self.global_avg_pool(x) # [B, C, 1, 1]
- F_max = self.global_max_pool(x) # [B, C, 1, 1]
- F_local = self.local_avg_pool(x) # [B, C, H, W]
- # Resize F_local for concatenation
- F_local_pooled = F.adaptive_avg_pool2d(F_local, (1, 1))
- # Concatenate pooled features
- F_pooled = torch.cat([F_avg, F_max, F_local_pooled], dim=1) # [B, 3*C, 1, 1]
- F_pooled = F_pooled.view(B, -1) # [B, 3*C]
- # Step 2: Hierarchical Channel-Wise Excitation
- F_excite = F.relu(self.fc1(F_pooled))
- F_excite = self.fc2(F_excite) # [B, C]
- channel_weights = torch.sigmoid(F_excite).view(B, C, 1, 1) # [B, C, 1, 1]
- # Channel modulation
- F_c = x * channel_weights.expand_as(x) # [B, C, H, W]
- # Step 3: Spatial Attention
- spatial_weights = self.spatial_conv(x) # [B, 1, H, W]
- spatial_weights = torch.sigmoid(spatial_weights) # [B, 1, H, W]
- # Step 4: Apply spatial attention
- F_out = F_c * spatial_weights.expand_as(F_c)
- return F_out
- # ==================== FA-CBAM Module ====================
- class FA_CBAM(nn.Module):
- """
- Feature-Aware Convolution Block Attention Module
- Combines spatial, channel, and frequency domain attention
- """
- def __init__(self, in_channels: int, reduction_ratio: int = 16):
- super().__init__()
- self.in_channels = in_channels
- # Channel Attention
- reduced_channels = max(in_channels // reduction_ratio, 4)
- self.channel_attention = nn.Sequential(
- nn.AdaptiveAvgPool2d(1),
- nn.Flatten(),
- nn.Linear(in_channels, reduced_channels, bias=False),
- nn.ReLU(inplace=True),
- nn.Linear(reduced_channels, in_channels, bias=False),
- nn.Sigmoid()
- )
- # Spatial Attention
- self.spatial_attention = nn.Sequential(
- nn.Conv2d(2, 1, kernel_size=7, padding=3, bias=False),
- nn.Sigmoid()
- )
- # Frequency domain processing
- self.freq_conv = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)
- # Fusion convolution
- self.fusion_conv = nn.Conv2d(2, 1, kernel_size=3, padding=1)
- def forward(self, x: torch.Tensor) -> torch.Tensor:
- """
- Args:
- x: Input feature map [B, C, H, W]
- Returns:
- Refined feature map [B, C, H, W]
- """
- B, C, H, W = x.shape
- # Step 1: Channel Attention
- channel_weights = self.channel_attention(x).view(B, C, 1, 1)
- F_c = x * channel_weights.expand_as(x)
- # Step 2: Spatial Attention
- # Average and max pooling along channel axis
- avg_pool = torch.mean(F_c, dim=1, keepdim=True) # [B, 1, H, W]
- max_pool, _ = torch.max(F_c, dim=1, keepdim=True) # [B, 1, H, W]
- spatial_input = torch.cat([avg_pool, max_pool], dim=1) # [B, 2, H, W]
- spatial_weights = self.spatial_attention(spatial_input) # [B, 1, H, W]
- F_s = F_c * spatial_weights
- # Step 3: Frequency Domain Augmentation
- F_freq = dct2d(x) # Apply DCT
- F_freq = self.freq_conv(F_freq) # Convolution on frequency features
- # Step 4: Fusion via Convolution
- # Resize spatial weights to match frequency features if needed
- if spatial_weights.shape[-2:] != F_freq.shape[-2:]:
- spatial_weights = F.interpolate(spatial_weights, size=F_freq.shape[-2:],
- mode='bilinear', align_corners=False)
- fusion_input = torch.cat([spatial_weights, F_freq], dim=1) # [B, C+1, H, W]
- # We need to adjust for channel mismatch - use pointwise conv
- if fusion_input.shape[1] != 2: # If not 2 channels, reduce
- fusion_input = fusion_input[:, :2, :, :] # Simple slice for demo
- M_sf = torch.sigmoid(self.fusion_conv(fusion_input)) # [B, 1, H, W]
- # Step 5: Final Output
- if M_sf.shape[-2:] != F_c.shape[-2:]:
- M_sf = F.interpolate(M_sf, size=F_c.shape[-2:], mode='bilinear', align_corners=False)
- F_out = F_c * M_sf.expand_as(F_c)
- return F_out
- # ==================== Main LogoXpertNet Model ====================
- class LogoXpertNet(nn.Module):
- """
- Complete LogoXpertNet model for logo classification
- """
- def __init__(self, num_classes: int = 32, pretrained_backbone: bool = True):
- super().__init__()
- # 1. Modified MobileNetV3 backbone
- self.backbone = ModifiedMobileNetV3(num_classes=num_classes,
- pretrained=pretrained_backbone)
- # Get feature dimensions from backbone
- early_channels = 24 # Based on MobileNetV3-small architecture
- deep_channels = 576 # Final feature dimension
- # 2. CLFF Module
- self.clff = CLFF(early_channels=early_channels,
- deep_channels=deep_channels,
- fusion_method='concat')
- # 3. HSE-SAB Module
- self.hse_sab = HSE_SAB(in_channels=early_channels + deep_channels) # After concatenation
- # 4. FA-CBAM Module
- self.fa_cbam = FA_CBAM(in_channels=early_channels + deep_channels)
- # 5. Classification head
- # After attention modules, we need to reduce spatial dimensions
- self.global_pool = nn.AdaptiveAvgPool2d(1)
- # Calculate input features to classifier
- classifier_input = early_channels + deep_channels
- self.classifier = nn.Sequential(
- nn.Dropout(0.2),
- nn.Linear(classifier_input, 1024),
- nn.ReLU(inplace=True),
- nn.Dropout(0.2),
- nn.Linear(1024, num_classes)
- )
- # Initialize weights
- self._initialize_weights()
- def _initialize_weights(self):
- """Initialize weights for custom modules"""
- for m in self.modules():
- if isinstance(m, nn.Conv2d):
- nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
- if m.bias is not None:
- nn.init.constant_(m.bias, 0)
- elif isinstance(m, nn.BatchNorm2d):
- nn.init.constant_(m.weight, 1)
- nn.init.constant_(m.bias, 0)
- elif isinstance(m, nn.Linear):
- nn.init.normal_(m.weight, 0, 0.01)
- if m.bias is not None:
- nn.init.constant_(m.bias, 0)
- def forward(self, x: torch.Tensor) -> torch.Tensor:
- """
- Forward pass through LogoXpertNet
- Args:
- x: Input images [B, 3, 224, 224]
- Returns:
- Class logits [B, num_classes]
- """
- # 1. Extract features from backbone
- early_feat, deep_feat_pooled = self.backbone(x)
- # 2. Prepare deep features for CLFF (need spatial dimensions)
- # In a full implementation, you'd store intermediate spatial features
- # For now, we'll create a placeholder
- B, C_early, H, W = early_feat.shape
- # Create a placeholder for deep spatial features
- # In practice, you'd extract this from an intermediate layer
- deep_feat_spatial = F.interpolate(
- deep_feat_pooled.view(B, -1, 1, 1),
- size=(H, W),
- mode='bilinear',
- align_corners=False
- )
- # 3. Apply CLFF
- clff_output = self.clff(early_feat, deep_feat_spatial)
- # 4. Apply HSE-SAB
- hse_sab_output = self.hse_sab(clff_output)
- # 5. Apply FA-CBAM
- fa_cbam_output = self.fa_cbam(hse_sab_output)
- # 6. Global pooling and classification
- pooled = self.global_pool(fa_cbam_output)
- flattened = torch.flatten(pooled, 1)
- # 7. Final classification
- logits = self.classifier(flattened)
- return logits
- def get_attention_maps(self, x: torch.Tensor):
- """
- Extract attention maps for visualization
- Returns intermediate attention outputs
- """
- attention_maps = {}
- # Extract features
- early_feat, deep_feat_pooled = self.backbone(x)
- B, C_early, H, W = early_feat.shape
- # Create placeholder for deep spatial features
- deep_feat_spatial = F.interpolate(
- deep_feat_pooled.view(B, -1, 1, 1),
- size=(H, W),
- mode='bilinear',
- align_corners=False
- )
- # Get CLFF output
- clff_output = self.clff(early_feat, deep_feat_spatial)
- attention_maps['clff'] = clff_output
- # Get HSE-SAB output
- hse_sab_output = self.hse_sab(clff_output)
- attention_maps['hse_sab'] = hse_sab_output
- # Get FA-CBAM output
- fa_cbam_output = self.fa_cbam(hse_sab_output)
- attention_maps['fa_cbam'] = fa_cbam_output
- return attention_maps
- # ==================== Utility Functions ====================
- def create_logoxpertnet(model_name: str = 'small', num_classes: int = 32,
- pretrained: bool = True) -> LogoXpertNet:
- """
- Factory function to create LogoXpertNet models
- """
- if model_name == 'small':
- return LogoXpertNet(num_classes=num_classes, pretrained_backbone=pretrained)
- else:
- raise ValueError(f"Unknown model name: {model_name}")
- def count_parameters(model: nn.Module) -> int:
- """Count total trainable parameters"""
- return sum(p.numel() for p in model.parameters() if p.requires_grad)
- def test_model():
- """Test the model with dummy data"""
- print("Testing LogoXpertNet implementation...")
- # Create model
- model = create_logoxpertnet(num_classes=32, pretrained=False)
- # Count parameters
- total_params = count_parameters(model)
- print(f"Total parameters: {total_params:,}")
- # Test forward pass
- batch_size = 4
- dummy_input = torch.randn(batch_size, 3, 224, 224)
- # Test inference
- model.eval()
- with torch.no_grad():
- output = model(dummy_input)
- print(f"Input shape: {dummy_input.shape}")
- print(f"Output shape: {output.shape}")
- print(f"Output range: [{output.min():.3f}, {output.max():.3f}]")
- # Test attention maps
- attention_maps = model.get_attention_maps(dummy_input)
- print(f"\nAttention maps keys: {list(attention_maps.keys())}")
- for key, value in attention_maps.items():
- print(f"{key} shape: {value.shape}")
- print("\nModel test completed successfully!")
- return model
- # ==================== Example Usage ====================
- if __name__ == "__main__":
- # Test the model
- model = test_model()
- # Example of how to use the model
- print("\n" + "="*50)
- print("Example Usage:")
- print("="*50)
- print("""
- # Create model for FlickrLogos-32 (32 classes)
- model = create_logoxpertnet(num_classes=32, pretrained=True)
- # Move to GPU if available
- device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
- model = model.to(device)
- # Prepare input
- batch = torch.randn(8, 3, 224, 224).to(device)
- # Forward pass
- logits = model(batch)
- # Get predictions
- predictions = torch.argmax(logits, dim=1)
- # Get attention maps for visualization
- attention_maps = model.get_attention_maps(batch)
- """)
- # Model summary
- print(f"\nModel Summary:")
- print(f"- Backbone: Modified MobileNetV3-small")
- print(f"- CLFF: Cross-Layer Feature Fusion")
- print(f"- HSE-SAB: Hierarchical Squeeze-Excitation Spatial Attention")
- print(f"- FA-CBAM: Feature-Aware Convolution Block Attention Module")
- print(f"- Output: {model.classifier[-1].out_features} classes")
LogoXpertNet Model.py at commit 01d679a, no license · at the source
Overview
- Faculty of Informatics and Computing, Universiti Sultan Zainal Abidin (UniSZA),Terengganu, Malaysia
- School of Computer Science and Technology, Harbin Institute of Technology,Shenzhen, 518055 China
- Department of Computer Science, University of Sahiwal,Sahiwal, Punjab Pakistan
- College of Computer and Information Sciences, Imam Mohammad Ibn Saud Islamic University (IMSIU),13318 Riyadh, Saudi Arabia
Abstract
Logo classification is crucial in various applications, including brand monitoring, copyright protection, and digital forensics. Traditional computer vision techniques face significant limitations, particularly in handling scale variations, occlusions, and background clutter. While deep learning models, particularly convolutional neural networks (CNNs), offer superior solutions, they often come with high computational costs, posing challenges for real-time deployment. This paper introduces LogoXpertNet, a lightweight deep learning architecture specifically designed for efficient logo classification. The key innovations of LogoXpertNet include: (1) a modified MobileNetV3 backbone enhanced with bottleneck and squeeze-and-excitation (SE) blocks for efficient feature extraction; (2) a novel cross-layer feature fusion (CLFF) module that improves feature integration across network depths; (3) a newly proposed hierarchical squeeze-excitation spatial attention block (HSE-SAB) that dynamically attends to both spatial and channel-wise features; and (4) a feature-aware convolution block attention module (FA-CBAM) that uniquely fuses spatial and frequency-domain information for refined logo attention. Extensive experiments on the evaluated benchmark datasets, including FlickrLogos-32, BelgaLogos, and WebLogo-2M, show that LogoXpertNet achieves strong classification performance while maintaining low computational overhead. Because the reported accuracies approach saturation on these benchmarks, the results should be interpreted in the context of dataset characteristics, split construction, and metric definition rather than as evidence of universal performance across all real-world logo-recognition scenarios. LogoXpertNet provides an efficient and practical framework for benchmark logo classification and offers a promising basis for future validation under more challenging real-world conditions.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 11 matches between paragraphs and lines of code.
Usman548/LogoXpertNet
01d679a39be1ce0298b6e084707093c093b1e667, 14 January 2026Availability: 1 check, the latest on 30 September 2026: the link answers
- 30 September 2026: the link answers
1 file
- LogoXpertNet Model.py, Python, 574 lines, 11 matches
Code availability
The implementation code of the LogoXpertNet is available at https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 1 script, each with its path and the digest of its content;
- 11 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- kaggle.com/
datasets/ , at Kaggle; found in the referencesviswanathv
Data availability
This research employed the publicly accessible datasets, which can be downloaded from the following links: Flickr32-Logos: https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 30 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 6 authors, 7 keywords, 1 funder, 19 references.
Cite
This paper
Mumtaz, M. T., Awang, M. K., Saeed, M. U., Hussain, S., Ben Noureddine, D., & Daadaa, Y. (2026). LogoXpertNet: a novel lightweight logo classification using deep learning. Scientific reports, 16(1), 10956. https://
BibTeX
@article{mumtaz2026logox
author = {Mumtaz, Muhammad Tahir and Awang, Mohd Khalid and Saeed, Muhammad Usman and Hussain, Shafiq and Ben Noureddine, Dhouha and Daadaa, Yassine},
title = {{LogoXpertNet: a novel lightweight logo classification using deep learning}},
journal = {Scientific reports},
year = {2026},
month = mar,
volume = {16},
number = {1},
pages = {10956},
publisher = {Nature Publishing Group},
issn = {2045-2322},
doi = {10.1038/
url = {https://
pmid = {41888352},
pmcid = {PMC13039303}
}
RIS
TY - JOUR
AU - Mumtaz, Muhammad Tahir
AU - Awang, Mohd Khalid
AU - Saeed, Muhammad Usman
AU - Hussain, Shafiq
AU - Ben Noureddine, Dhouha
AU - Daadaa, Yassine
TI - LogoXpertNet: a novel lightweight logo classification using deep learning
T2 - Scientific reports
J2 - Sci Rep
PY - 2026
DA - 2026/
VL - 16
IS - 1
SP - 10956
SN - 2045-2322
PB - Nature Publishing Group
DO - 10.1038/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1038/
"type": "article-journal",
"title": "LogoXpertNet: a novel lightweight logo classification using deep learning",
"container-title": "Scientific reports",
"author": [
{
"family": "Mumtaz",
"given": "Muhammad Tahir"
},
{
"family": "Awang",
"given": "Mohd Khalid"
},
{
"family": "Saeed",
"given": "Muhammad Usman"
},
{
"family": "Hussain",
"given": "Shafiq"
},
{
"family": "Ben Noureddine",
"given": "Dhouha"
},
{
"family": "Daadaa",
"given": "Yassine"
}
],
"container-title-short":
"volume": "16",
"issue": "1",
"page": "10956",
"DOI": "10.1038/
"PMID": "41888352",
"PMCID": "PMC13039303",
"ISSN": "2045-2322",
"publisher": "Nature Publishing Group",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
26
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
No other paper with a page shares enough with this one yet: tools, categories, datasets, references or authors.
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 1 script, and 11 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:28bb01baaf119d12…
Add the badge to the code's README
If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.
Markdown
<!-- oscr-badge:start -->
[](https://openscicode.org/badge/doi/10.1038/s41598-026-45682-z)
<!-- oscr-badge:end -->reStructuredText
.. oscr-badge:start
.. image:: https://openscicode.org/badge/doi/10.1038/s41598-026-45682-z.svg
:target: https://openscicode.org/badge/doi/10.1038/s41598-026-45682-z
:alt: OSCR
.. oscr-badge:endHTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1038/s41598-026-45682-z"><img src="https://openscicode.org/badge/doi/10.1038/s41598-026-45682-z.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".
If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge page.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.
Report a mismatch between the code and the paper · Report a code error (signed in)
Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.
Report a reproduction failure (signed in)
Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
