Integrating Hikvision License Plate Recognition with C# Applications

System Architecutre Overview

Core Component Structure

public class LprEngine {
    private readonly HCNetSDK _sdkHandler;
    private readonly List<SurveillanceCamera> _cameras;

    public LprEngine() {
        _sdkHandler = new HCNetSDK();
        _cameras = new List<SurveillanceCamera>();
    }

    public bool StartupSystem() {
        if (!_sdkHandler.NET_DVR_Init()) return false;
        
        var discoveredUnits = CameraDiscoveryService.DetectAll();
        _cameras.AddRange(discoveredUnits.Select(ip => new SurveillanceCamera(ip)));

        return _cameras.TrueForAll(cam => cam.Authenticate());
    }
}

Device Communication Layer

public class SurveillanceCamera {
    public string Address { get; set; }
    public int ConnectionPort { get; set; }
    public string User { get; set; }
    public string Secret { get; set; }

    public bool Authenticate() {
        var authParams = new NET_DVR_USER_LOGIN_INFO {
            sDeviceAddress = Encoding.ASCII.GetBytes(Address),
            wPort = (ushort)ConnectionPort,
            sUserName = Encoding.ASCII.GetBytes(User),
            sPassword = Encoding.ASCII.GetBytes(Secret)
        };

        return _sdkHandler.NET_DVR_Login_V40(ref authParams, out _) >= 0;
    }
}

Key Feature Implementation

Live Video Stream Handling

public void BeginStreamDisplay(PictureBox displayArea) {
    var streamConfig = new NET_DVR_PREVIEWINFO {
        hPlayWnd = displayArea.Handle,
        dwStreamType = 0,
        dwLinkMode = 1
    };

    _sdkHandler.NET_DVR_RealPlay_V40(_deviceId, ref streamConfig, null, IntPtr.Zero);
}

License Plate Detection Settings

public void SetupDetectionParameters() {
    var config = new NET_DVR_PLATECFG {
        byPlateTriggerType = 1,
        byPicQuality = 3,
        byMinPlateWidth = 90
    };

    uint size = (uint)Marshal.SizeOf(config);
    _sdkHandler.NET_DVR_SetDVRConfig(_deviceId, HCNetSDK.NET_DVR_SET_PLATECFG, 0, ref config, size);
}

Alarm Event Processing

private void AlarmReceived(ref NET_DVR_ALARMER alarmer, IntPtr rawData, uint dataLength) {
    var detectionResult = (NET_ITS_PLATE_RESULT)Marshal.PtrToStructure(rawData, typeof(NET_ITS_PLATE_RESULT));
    
    string license = Encoding.GetEncoding("GBK").GetString(detectionResult.struPlateInfo.sLicense).TrimEnd('\0');
    DateTime timestamp = DateTime.FromFileTimeUtc((long)detectionResult.dwUTC);

    OnLicenseSpotted?.Invoke(license, timestamp, detectionResult.struPicInfo.pBuffer);
}

Hardware Integration Features

LED Sign Control via ISAPI

public static void UpdateDisplay(string host, string content) {
    string endpoint = "/ISAPI/Parking/channels/1/LEDConfigurationDz";
    var doc = new XmlDocument();
    doc.LoadXml($"<LEDConfigurationList><LEDConfiguration><information>{content}</information></LEDConfiguration></LEDConfigurationList>");
    
    HttpDigestClient.Post(host, endpoint, doc.OuterXml, "admin", "password");
}

Voice Announcement Functionality

public static void BroadcastMessage(string deviceIp, string announcement) {
    string path = "/ISAPI/Parking/channels/1/voiceBroadcastInfo";
    var payload = new XmlDocument();
    payload.LoadXml($"<VoiceBroadcastInfo><information>{announcement}</information></VoiceBroadcastInfo>");
    
    HttpDigestClient.Post(deviceIp, path, payload.OuterXml, "admin", "password");
}

Performance Enhancements

Concurrent Processing Framework

private readonly Channel<VideoFrame> _processingPipeline = Channel.CreateUnbounded<VideoFrame>();

public async Task StartProcessingAsync() {
    await foreach (var frame in _processingPipeline.Reader.ReadAllAsync()) {
        await Task.Run(() => AnalyzeFrame(frame));
    }
}

Image Enhancement Routine

public Bitmap ImproveClarity(Bitmap input) {
    using var grayImage = OpenCvSharp.Cv2.CvtColor(input, OpenCvSharp.ColorConversionCodes.BGR2GRAY);
    OpenCvSharp.Cv2.GaussianBlur(grayImage, grayImage, new OpenCvSharp.Size(3, 3), 1.5);
    OpenCvSharp.Cv2.Threshold(grayImage, grayImage, 0, 255, OpenCvSharp.ThresholdTypes.Otsu);

    return OpenCvSharp.Cv2.ToBitmap(grayImage);
}

Testing and Deployment Guidelines

Test Scenario Matrix

Scenario Conditions Expected Outcome
Daylight Operation Speed: 25km/h, Clear plate visibility Detection rate ≥ 99%
Backlit Conditions Illuminance > 8000 lux Recognition accuracy ≥ 94%
Partial Occlusion Occluded area ≤ 25% Correct character extraction
High-Speed Capture Vehicle speed: 70km/h Processing rate ≥ 25 FPS

Deployment Configuration

[RuntimeSettings]
SdkRoot=C:\Program Files\Hikvision\SDK
LogLevel=Warning
MonitoringPort=7200

[HardwareSetup]
CameraCount=6
LedSignEndpoint=192.168.1.105
AudioModuleBaud=115200

Error Recovery Mechanism

Device Health Monitoring

private void MonitorHardwareStatus() {
    foreach (var unit in _cameras) {
        var deviceInfo = new NET_DVR_DEVICEINFO_V40();
        if (_sdkHandler.NET_DVR_GetDVRConfig(unit.Id, HCNetSDK.NET_DVR_GET_DEVICEINFO, 0, ref deviceInfo, 
            (uint)Marshal.SizeOf(deviceInfo)) < 0) {
            AttemptReconnection(unit);
        }
    }
}

private void AttemptReconnection(SurveillanceCamera camera) {
    for (int attempt = 0; attempt < 3; attempt++) {
        if (camera.Authenticate()) {
            camera.RestartStream();
            return;
        }
        Thread.Sleep(6000);
    }
    EventLog.WriteEntry("LPR System", $"Failed to restore connection to {camera.Address}", EventLogEntryType.Error);
}

Extended Capabilities

Traffic Volume Analytics

public class TrafficAnalyzer {
    private readonly ConcurrentDictionary<DateTime, int> _hourlyTally = new();

    public void RecordPassing() {
        var hourKey = DateTime.Now.RoundDown(TimeSpan.FromHours(1));
        _hourlyTally.AddOrUpdate(hourKey, 1, (key, value) => value + 1);
    }
}

Vehicle Tracking Algorithm

public class VehicleTracker {
    private readonly KalmanFilter _tracker;

    public VehicleTracker() {
        _tracker = new KalmanFilter(4, 2);
        _tracker.TransitionMatrix = Mat.Eye(4, 4, MatType.CV_32F);
    }

    public PointF EstimateNextPosition(PointF current) {
        var measurement = new Mat(2, 1, MatType.CV_32F);
        measurement.Set(0, current.X);
        measurement.Set(1, current.Y);

        _tracker.Predict();
        _tracker.Update(measurement);
        
        return new PointF(_tracker.StatePost.Get<float>(0), _tracker.StatePost.Get<float>(1));
    }
}

Integration Recomendations

  1. Database Schema``` CREATE TABLE CapturedPlates ( Id INT IDENTITY(1,1) PRIMARY KEY, License VARCHAR(15) NOT NULL, Timestamp DATETIME2 DEFAULT GETUTCDATE(), VehicleClass TINYINT CHECK(VehicleClass BETWEEN 1 AND 8), Velocity DECIMAL(5,2), LaneNumber TINYINT, ImageReference NVARCHAR(300) )

    CREATE INDEX IX_CapturedPlates_Timestamp ON CapturedPlates(Timestamp)

  2. REST API Endpoint``` [HttpPost("api/v1/detections")] public IActionResult ProcessImage([FromForm] IFormFile imageFile) { if (imageFile == null || imageFile.Length == 0) return BadRequest("No image provided");

     using var memoryStream = new MemoryStream();
     imageFile.CopyTo(memoryStream);
    
     var recognitionResult = LicenseDetector.Execute(memoryStream.ToArray());
     return Ok(new { 
         Plate = recognitionResult.Number, 
         Confidence = recognitionResult.Confidence 
     });
    

    }

    
    

Benchmark Results

Model Number Frame Throughput Latency Max Channels
DS-TCG2WC-TB 38 FPS 75ms 16
DS-2CD2047G2-L 30 FPS 105ms 8
DS-2CD7A26G0/P-IZ 48 FPS 45ms 32

Troubleshooting Guide

  • Low Accuracy
    • Verify lighting uniformity (minimum 600 lux recommended)
    • Adjust detection sensitivity: NET_DVR_SetParameter(0x01, 0x04)
    • Upgrade OCR model files (*.omc)
  • Connection Drops
    • Enable keep-alive: NET_DVR_SetKeepAlive(1, 45000)
    • Configure retry behavior: sdk.NET_DVR_SetConnectTime(3000, 2)
  • Device Interference
    • Asssign dedicated ports: NET_DVR_SetCallback
    • Register unique identifiers: NET_DVR_AssignUniqueID

Tags: Hikvision C# license plate recognition HCNetSDK video analytics

Posted on Tue, 06 Oct 2026 16:12:57 +0000 by duankr