Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
875e846470 | ||
|
86b22c6d86 | ||
|
693d4535c9 | ||
|
86ebf2d316 | ||
81611cd8cb | |||
|
e123c18120 | ||
|
909d28fd65 | ||
|
31b6185f33 | ||
|
470b364fbc | ||
|
2ba1f47010 | ||
|
040f19ca78 | ||
|
06d459d2db | ||
|
e49d28c72e | ||
|
69628be9ce | ||
|
327faae0bc | ||
|
6f1cc96c16 | ||
|
15112abac9 | ||
|
71c437d8d7 | ||
|
7ee7ebc4b3 | ||
|
527be316ff | ||
|
0b3b898ccf |
25
.dockerignore
Normal file
25
.dockerignore
Normal file
@ -0,0 +1,25 @@
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/azds.yaml
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
37
Dockerfile
Normal file
37
Dockerfile
Normal file
@ -0,0 +1,37 @@
|
||||
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-bionic AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-bionic AS build
|
||||
WORKDIR /src
|
||||
|
||||
COPY ["squirrowse.web/squirrowse.web.csproj", "squirrowse.web/"]
|
||||
COPY ["squirrowse.core/squirrowse.core.csproj", "squirrowse.core/"]
|
||||
COPY ["squirrowse.db/squirrowse.db.csproj", "squirrowse.db/"]
|
||||
COPY ["squirrowse.web/NuGet.Config", "squirrowse.core/"]
|
||||
COPY ["squirrowse.web/NuGet.Config", "squirrowse.web/"]
|
||||
COPY ["squirrowse.web/NuGet.Config", "squirrowse.db/"]
|
||||
COPY . .
|
||||
RUN dotnet restore "squirrowse.web/squirrowse.web.csproj" --configfile ./NuGet.Config
|
||||
|
||||
WORKDIR "/src/squirrowse.web"
|
||||
RUN dotnet build "squirrowse.web.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "squirrowse.web.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y libgtk2.0-dev
|
||||
RUN apt-get -y update
|
||||
RUN apt-get -y install wget unzip build-essential checkinstall cmake pkg-config yasm git gfortran libjpeg8-dev libpng-dev software-properties-common
|
||||
RUN add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
|
||||
RUN apt-get -y update && apt -y install libjasper1 libtiff-dev libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev libxine2-dev libv4l-dev
|
||||
RUN apt-get -y install libgtk2.0-dev libtbb-dev libatlas-base-dev libvorbis-dev libxvidcore-dev libopencore-amrnb-dev libopencore-amrwb-dev libavresample-dev x264 v4l-utils libwebp-dev tesseract-ocr libtesseract-dev libleptonica-dev
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "squirrowse.web.dll"]
|
7
NuGet.Config
Normal file
7
NuGet.Config
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
<add key="devexpress" value="https://nuget.devexpress.com/ABUfBvYl5nEk34zibEAYwSnHnPjgCvnCPvQjGXho1rjvWetBmz/api" />
|
||||
</packageSources>
|
||||
</configuration>
|
@ -1,11 +1,8 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Squirrowse.Client.Service;
|
||||
using Squirrowse.Core.Services;
|
||||
|
||||
namespace Squirrowse.Client
|
||||
namespace squirrowse.client
|
||||
{
|
||||
public class Program
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
@ -17,13 +14,14 @@ namespace Squirrowse.Client
|
||||
return Host.CreateDefaultBuilder(args)
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
|
||||
services.AddHostedService<Worker>();
|
||||
services.AddSingleton<IConnectionManager>(x =>
|
||||
new ConnectionManager("http://localhost", 5000)); //keep as transient for now
|
||||
services.AddSingleton<ICameraService, CameraService>(x => new CameraService(new Camera()));
|
||||
services.AddSingleton<IActionDispatcher, ActionDispatcher>();
|
||||
new ConnectionManager("http://squirrowse.azurewebsites.net", 80)); //keep as transient for now
|
||||
|
||||
// new ConnectionManager("http://192.168.0.13", 5000)); //keep as transient for now
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,23 +10,27 @@ namespace Squirrowse.Client.Service
|
||||
{
|
||||
public class ActionDispatcher : IActionDispatcher
|
||||
{
|
||||
private readonly ICameraService camera;
|
||||
private readonly IConnectionManager connectionManager;
|
||||
private readonly ILogger<ActionDispatcher> logger;
|
||||
private readonly HubConnection session;
|
||||
private readonly ICameraService camera;
|
||||
|
||||
public ActionDispatcher(ILogger<ActionDispatcher> logger, IConnectionManager connectionManager,ICameraService camera)
|
||||
private bool streamOn = false;
|
||||
public ActionDispatcher(ILogger<ActionDispatcher> logger, IConnectionManager connectionManager,
|
||||
ICameraService camera)
|
||||
{
|
||||
this.connectionManager = connectionManager;
|
||||
this.logger = logger;
|
||||
this.camera = camera;
|
||||
session.On("Start", StartStream);
|
||||
session = connectionManager.GetConnection().Result;
|
||||
session.On("Start", StartStream);
|
||||
//session.On("StartEnum", StartStreamEnumerable);
|
||||
session.On("Stop", StopStream);
|
||||
}
|
||||
|
||||
public Task StopStream()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
streamOn = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task SayHello()
|
||||
@ -36,15 +40,22 @@ namespace Squirrowse.Client.Service
|
||||
|
||||
public async Task SendStreamAsync(IAsyncEnumerable<byte[]> asb)
|
||||
{
|
||||
if(!streamOn)return;
|
||||
logger.LogInformation($"{nameof(SendStreamAsync)} Start stream");
|
||||
|
||||
await session.SendAsync("UploadByteStream", asb);
|
||||
|
||||
logger.LogInformation($"{nameof(SendStreamAsync)} End stream");
|
||||
}
|
||||
|
||||
|
||||
public async Task StartStream()
|
||||
{
|
||||
if (streamOn) return;
|
||||
streamOn = true;
|
||||
await SendStreamAsync(camera.GetFramesAsyncEnumerator());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -23,8 +23,12 @@ namespace Squirrowse.Client.Service
|
||||
|
||||
public async IAsyncEnumerable<byte[]> GetFramesAsyncEnumerator()
|
||||
{
|
||||
using var fr = await GetFrame();
|
||||
yield return fr.ConvertToJpgByte();
|
||||
while (true)
|
||||
{
|
||||
using var fr = await GetFrame();
|
||||
yield return fr.ConvertToJpgByte();
|
||||
await Task.Delay(1000 / 30);
|
||||
}
|
||||
//fr.Dispose();
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<UserSecretsId>dotnet-Squirrowse.Client-D6805387-040A-46DF-9DAE-926B46C981A6</UserSecretsId>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4.Windows" Version="4.1.1.20191021" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.2" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.2.0.20200208" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.2.0.20200208" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Squirrowse.Core\Squirrowse.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1,30 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Squirrowse.Client.Service;
|
||||
using Squirrowse.Core.Models;
|
||||
using Squirrowse.Core.Services;
|
||||
|
||||
namespace Squirrowse.Client
|
||||
namespace squirrowse.client
|
||||
{
|
||||
public class Worker : IHostedService
|
||||
{
|
||||
private readonly IConnectionManager _connectionManager;
|
||||
private readonly ICameraService camera;
|
||||
private readonly ILogger<Worker> logger;
|
||||
|
||||
public Worker(ILogger<Worker> logger, IConnectionManager connectionManager, ICameraService camera)
|
||||
private readonly IConnectionManager _connectionManager;
|
||||
private Connection con =new Connection();
|
||||
public Worker(ILogger<Worker> logger, IConnectionManager connectionManager)
|
||||
{
|
||||
this.logger = logger;
|
||||
_connectionManager = connectionManager;
|
||||
this.camera = camera;
|
||||
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _connectionManager.InitConnection(ConnectionType.Client);
|
||||
|
||||
await _connectionManager.InitConnection();
|
||||
|
||||
//var d = _connectionManager.GetConnection();
|
||||
if (_connectionManager.IsConnected())
|
||||
{
|
||||
var d =await _connectionManager.GetConnection();
|
||||
await d.SendAsync("UploadStream", con.clientStreamData());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
@ -32,4 +38,4 @@ namespace Squirrowse.Client
|
||||
await _connectionManager.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
"Microsoft": "Information",
|
||||
"Microsoft.AspNetCore.SignalR": "Debug",
|
||||
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ namespace Squirrowse.Core
|
||||
public static IServiceCollection AddCoreModule(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
|
||||
services.AddSingleton<IConnectionManager>(x =>
|
||||
services.AddSingleton<IConnectionManager, ConnectionManager>(x =>
|
||||
new ConnectionManager("http://localhost", 5000));
|
||||
return services;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
public enum ConnectionType
|
||||
{
|
||||
Unknown=-1,
|
||||
Unknown = -1,
|
||||
Client,
|
||||
Server,
|
||||
Root
|
||||
|
@ -6,7 +6,7 @@
|
||||
{
|
||||
ConnectionId = connectionId;
|
||||
AgentName = agentName;
|
||||
this.UserType = userType;
|
||||
UserType = userType;
|
||||
}
|
||||
|
||||
public string ConnectionId { get; set; }
|
||||
|
@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using Squirrowse.Core.Models;
|
||||
using System;
|
||||
|
||||
namespace Squirrowse.Client.Models
|
||||
{
|
||||
public class VideoFrame
|
||||
public class VStream
|
||||
{
|
||||
public User user { get; set; }
|
||||
public byte[] FrameBytes { get; set; }
|
||||
public DateTime TimeStamp => DateTime.Now;
|
||||
public Guid id => Guid.NewGuid();
|
@ -22,17 +22,17 @@ namespace Squirrowse.Core.Services
|
||||
|
||||
public async Task<HubConnection> GetConnection()
|
||||
{
|
||||
if (Connected) return _connection;
|
||||
|
||||
throw new Exception();
|
||||
return _connection;
|
||||
}
|
||||
|
||||
public async Task InitConnection(ConnectionType type)
|
||||
{
|
||||
if (_connection.State == HubConnectionState.Connected) return;
|
||||
await _connection.StartAsync();
|
||||
await RegisterOnHub(type);
|
||||
Connected = true;
|
||||
if (_connection.State == HubConnectionState.Disconnected) await _connection.StartAsync();
|
||||
|
||||
await RegisterOnHub(type);
|
||||
Connected = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -45,8 +45,7 @@ namespace Squirrowse.Core.Services
|
||||
|
||||
private async Task RegisterOnHub(ConnectionType type)
|
||||
{
|
||||
await _connection.SendAsync("AddUser", Environment.UserName,type);
|
||||
await _connection.SendAsync("AddUser", Environment.UserName, type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,13 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4.Windows" Version="4.1.1.20191021" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.Azure.CognitiveServices.Vision.ComputerVision" Version="6.0.0-dev.20190919.3" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.2.0.20200208" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.ubuntu.18.04-x64" Version="4.2.0.20200208" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
21
Squirrowse.Service/Dockerfile
Normal file
21
Squirrowse.Service/Dockerfile
Normal file
@ -0,0 +1,21 @@
|
||||
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 5000
|
||||
EXPOSE 5001
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
|
||||
WORKDIR /src
|
||||
COPY ["Squirrowse.Service/Squirrowse.Service.csproj", "Squirrowse.Service/"]
|
||||
COPY ["Squirrowse.Core/Squirrowse.Core.csproj", "Squirrowse.Core/"]
|
||||
RUN dotnet restore "Squirrowse.Service/Squirrowse.Service.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/Squirrowse.Service"
|
||||
RUN dotnet build "Squirrowse.Service.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "Squirrowse.Service.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "Squirrowse.Service.dll"]
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Squirrowse.Core.Models;
|
||||
|
||||
@ -7,7 +6,7 @@ namespace Squirrowse.Service.Hubs
|
||||
{
|
||||
public interface IStreamHub
|
||||
{
|
||||
Task AddUser(string username,ConnectionType type);
|
||||
Task AddUser(string username, ConnectionType type);
|
||||
Task UploadByteStream(IAsyncEnumerable<byte[]> stream);
|
||||
Task Startstream(string userId);
|
||||
Task StopStream(string userId);
|
||||
|
@ -6,12 +6,14 @@ namespace Squirrowse.Service.Hubs
|
||||
{
|
||||
public interface IStreamManager
|
||||
{
|
||||
Task AddUser(string connectionId, string agentName,ConnectionType type);
|
||||
Task AddUser(string connectionId, string agentName, ConnectionType type);
|
||||
Task RemoveUserbyConnectionId(string connectionId);
|
||||
Task RemoveUserByUserName(string agentName);
|
||||
IEnumerable<User> getServerSideUsers();
|
||||
IEnumerable<User> getServerSideUsers();
|
||||
bool CheckUser(string agentName);
|
||||
IEnumerable<User> getClientSideUsers();
|
||||
IEnumerable<User> getAllUsers();
|
||||
|
||||
Task SaveData(IAsyncEnumerable<byte[]> stream);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
@ -15,6 +16,7 @@ namespace Squirrowse.Service.Hubs
|
||||
private readonly ILogger<StreamHub> logger;
|
||||
private readonly IStreamManager manager;
|
||||
|
||||
|
||||
public StreamHub(ILogger<StreamHub> logger, IStreamManager manager)
|
||||
{
|
||||
this.logger = logger;
|
||||
@ -23,9 +25,18 @@ namespace Squirrowse.Service.Hubs
|
||||
|
||||
public async Task AddUser(string UserName, ConnectionType type)
|
||||
{
|
||||
await manager.AddUser(Context.ConnectionId, UserName,type);
|
||||
logger.LogInformation($"{nameof(AddUser)}: {UserName} of {type}");
|
||||
await manager.AddUser(Context.ConnectionId, UserName, type);
|
||||
switch (type)
|
||||
{
|
||||
case ConnectionType.Client:
|
||||
await AddToGroup(Core.Models.Groups.normal);
|
||||
break;
|
||||
case ConnectionType.Server:
|
||||
await AddToGroup(Core.Models.Groups.superUser);
|
||||
break;
|
||||
}
|
||||
|
||||
logger.LogInformation($"{nameof(AddUser)}: {UserName} of {type}");
|
||||
}
|
||||
|
||||
|
||||
@ -55,71 +66,78 @@ namespace Squirrowse.Service.Hubs
|
||||
|
||||
public async Task Startstream(string clientId)
|
||||
{
|
||||
var client = Clients.Client(clientId);
|
||||
|
||||
await client.SendAsync("Start");
|
||||
streamOn = true;
|
||||
//var client = Clients.Client(clientId);
|
||||
await Clients.Groups(Core.Models.Groups.normal.ToString()).SendAsync("Start");
|
||||
// await client.SendAsync("Start");
|
||||
}
|
||||
|
||||
|
||||
public async Task StopStream(string clientId)
|
||||
{
|
||||
var client = Clients.Client(clientId);
|
||||
|
||||
await client.SendAsync("Stop");
|
||||
streamOn = false;
|
||||
//var client = Clients.Client(clientId);
|
||||
// await Clients.Groups(Core.Models.Groups.normal.ToString()).SendAsync("Stop");
|
||||
//await client.SendAsync("Stop");
|
||||
}
|
||||
|
||||
public static bool streamOn { get; set; }
|
||||
|
||||
public async Task UploadByteStream(IAsyncEnumerable<byte[]> stream)
|
||||
{
|
||||
foreach (var user in manager.getServerSideUsers())
|
||||
|
||||
await foreach (var frame in stream)
|
||||
{
|
||||
await Clients.Client(user.ConnectionId).SendAsync("RecData", stream);
|
||||
}
|
||||
await foreach (var frame in stream)
|
||||
{
|
||||
logger.LogInformation($"Got frame size: {frame.Length} ");
|
||||
await Task.Delay(100); //leave some delay for debug purpose
|
||||
// var frameStamp = frame.ConvertByteToMat();
|
||||
// string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
|
||||
// CultureInfo.InvariantCulture);
|
||||
// Cv2.PutText(frameStamp, timestamp, new Point(1, 480 / 2), HersheyFonts.HersheySimplex, 0.5f, Scalar.Red);
|
||||
logger.LogInformation($"{this.GetHashCode()}: send frame");
|
||||
|
||||
//logger.LogInformation($"Got frame size: {frame.Length} ");
|
||||
//if (!streamOn) continue;
|
||||
// logger.LogInformation($"Send frame of size: {frame.Length} to {Core.Models.Groups.superUser.ToString()}");
|
||||
var framewithTs = await AddTimestamp(frame);
|
||||
await Clients.Groups(Core.Models.Groups.superUser.ToString()).SendAsync("RecData",framewithTs );
|
||||
logger.LogInformation($"{this.GetHashCode()}: send data");
|
||||
//await Task.Delay(100); //leave some delay for debug purpose
|
||||
await Task.Delay(1000 / 30);
|
||||
}
|
||||
}
|
||||
public async Task StartRecord(string connectionId)
|
||||
{
|
||||
|
||||
}
|
||||
public async Task StopRecord(string connectionId)
|
||||
{
|
||||
|
||||
}
|
||||
public async Task<byte[]> AddTimestamp(byte[] framebytes)
|
||||
{
|
||||
|
||||
var frameStamp = framebytes.ConvertByteToMat();
|
||||
string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
|
||||
CultureInfo.InvariantCulture);
|
||||
Cv2.PutText(frameStamp, timestamp, new Point(1, 480 / 2), HersheyFonts.HersheySimplex, 0.5f, Scalar.Red);
|
||||
return frameStamp.ConvertToJpgByte();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<User>> GetListOfTypeUser(ConnectionType t)
|
||||
{
|
||||
if (t == ConnectionType.Client) return manager.getClientSideUsers();
|
||||
if (t == ConnectionType.Server) return manager.getServerSideUsers();
|
||||
throw new Exception("not found") ;
|
||||
return manager.getAllUsers();
|
||||
}
|
||||
#warning DEBUG
|
||||
public async Task<string> GetListOfTypeUserString()
|
||||
{
|
||||
string t = "";
|
||||
var tasdf=manager.getClientSideUsers();
|
||||
foreach (var h in tasdf)
|
||||
{
|
||||
t +=h.AgentName;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
#warning DEBUG
|
||||
public async Task<User> Getasuser() => manager.getClientSideUsers().FirstOrDefault();
|
||||
#warning Debug
|
||||
public async Task<List<User>> GetListOfTypeUserE(ConnectionType t)
|
||||
{
|
||||
if (t == ConnectionType.Client) return manager.getClientSideUsers().ToList();
|
||||
if (t == ConnectionType.Server) return manager.getServerSideUsers().ToList();
|
||||
throw new Exception("not found");
|
||||
}
|
||||
#warning debug
|
||||
public async IAsyncEnumerable<User> GetListOfTypeUserAsync(ConnectionType t)
|
||||
{
|
||||
var client = manager.getClientSideUsers();
|
||||
foreach (var va in client)
|
||||
{
|
||||
yield return va;
|
||||
}
|
||||
}
|
||||
public async Task<IEnumerable<User>> GetAllUsers()
|
||||
{
|
||||
return manager.getAllUsers();
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<User> GetListOfTypeUserAsync(ConnectionType t)
|
||||
{
|
||||
var client = await GetListOfTypeUser(t);
|
||||
foreach (var va in client) yield return va;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using OpenCvSharp;
|
||||
using Squirrowse.Core.Models;
|
||||
using Squirrowse.Core.Services;
|
||||
|
||||
namespace Squirrowse.Service.Hubs
|
||||
{
|
||||
public class StreamManager : IStreamManager
|
||||
{
|
||||
private List<User> _users = new List<User>(); //temporary
|
||||
|
||||
public Task AddUser(string connectionId, string userName,ConnectionType type)
|
||||
private readonly List<User> _users = new List<User>(); //temporary
|
||||
public bool StreamOn { get; set; }
|
||||
public Task AddUser(string connectionId, string userName, ConnectionType type)
|
||||
{
|
||||
_users.Add(new User(connectionId, userName,type));
|
||||
_users.Add(new User(connectionId, userName, type));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@ -31,10 +34,13 @@ namespace Squirrowse.Service.Hubs
|
||||
{
|
||||
return _users.Where(user => user.UserType == ConnectionType.Server);
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<User> getClientSideUsers()
|
||||
{
|
||||
return _users.Where(user => user.UserType == ConnectionType.Client);
|
||||
}
|
||||
|
||||
public bool CheckUser(string userName)
|
||||
{
|
||||
return _users.Any(user => user.AgentName == userName);
|
||||
@ -42,8 +48,18 @@ namespace Squirrowse.Service.Hubs
|
||||
|
||||
public IEnumerable<User> getAllUsers()
|
||||
{
|
||||
var t = _users;
|
||||
// var t = _users;
|
||||
return _users;
|
||||
}
|
||||
|
||||
public async Task SaveData(IAsyncEnumerable<byte[]> stream)
|
||||
{
|
||||
VideoWriter output = new VideoWriter("m.avi",FourCC.DIVX,30,new Size(640,480));
|
||||
|
||||
await foreach (var b in stream)
|
||||
{
|
||||
output.Write(b.ConvertByteToMat());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
@ -8,11 +7,10 @@
|
||||
"sslPort": 44365
|
||||
}
|
||||
},
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": false,
|
||||
"launchUrl": "",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
@ -21,10 +19,22 @@
|
||||
"commandName": "Project",
|
||||
"launchBrowser": false,
|
||||
"launchUrl": "weatherforecast",
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000"
|
||||
},
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_URLS": "https://+:443;http://+:80",
|
||||
"ASPNETCORE_HTTPS_PORT": "44366"
|
||||
},
|
||||
"httpPort": 59338,
|
||||
"useSSL": true,
|
||||
"sslPort": 44366
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<UserSecretsId>996aee3a-63a2-4e6b-abcd-b0c6a183af8c</UserSecretsId>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -13,6 +15,7 @@
|
||||
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="3.0.0-*" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.5" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.0" />
|
||||
<PackageReference Include="System.Reactive.Linq" Version="4.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4.Windows" Version="4.1.1.20191021" />
|
||||
@ -22,10 +25,4 @@
|
||||
<ProjectReference Include="..\Squirrowse.Core\Squirrowse.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -24,7 +24,7 @@ namespace Squirrowse.Service
|
||||
{
|
||||
services.AddControllers();
|
||||
services.AddMediatR(Assembly.GetAssembly(typeof(Startup)));
|
||||
services.AddSingleton<IStreamHub, StreamHub>();
|
||||
//services.AddSingleton<IStreamHub, StreamHub>();
|
||||
services.AddSingleton<IStreamManager, StreamManager>();
|
||||
services.AddCoreModule();
|
||||
services.AddSignalR()
|
||||
|
@ -3,7 +3,9 @@
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
"Microsoft": "Information",
|
||||
"Microsoft.AspNetCore.SignalR": "Debug",
|
||||
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,9 @@
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
"Microsoft.Hosting.Lifetime": "Information",
|
||||
"Microsoft.AspNetCore.SignalR": "Debug",
|
||||
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||
}
|
||||
},
|
||||
"NLog": {
|
||||
|
BIN
Squirrowse.Service/dll/openh264-1.8.0-win64.dll
Normal file
BIN
Squirrowse.Service/dll/openh264-1.8.0-win64.dll
Normal file
Binary file not shown.
BIN
Squirrowse.Service/dupa.avi
Normal file
BIN
Squirrowse.Service/dupa.avi
Normal file
Binary file not shown.
BIN
Squirrowse.Service/dupa.mkv
Normal file
BIN
Squirrowse.Service/dupa.mkv
Normal file
Binary file not shown.
@ -1,10 +1,10 @@
|
||||
<Router AppAssembly="@typeof(Program).Assembly">
|
||||
<Router AppAssembly="@typeof(Program).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
</Found>
|
||||
<NotFound>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p>Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
</Router>
|
@ -1,15 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Squirrowse.Web.Data
|
||||
{
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
|
||||
public string Summary { get; set; }
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Squirrowse.Web.Data
|
||||
{
|
||||
public class WeatherForecastService
|
||||
{
|
||||
private static readonly string[] Summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
};
|
||||
|
||||
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
|
||||
{
|
||||
var rng = new Random();
|
||||
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = startDate.AddDays(index),
|
||||
TemperatureC = rng.Next(-20, 55),
|
||||
Summary = Summaries[rng.Next(Summaries.Length)]
|
||||
}).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
@page "/counter"
|
||||
|
||||
<h1>Counter</h1>
|
||||
|
||||
<p>Current count: @currentCount</p>
|
||||
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
int currentCount = 0;
|
||||
|
||||
void IncrementCount()
|
||||
{
|
||||
currentCount++;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
@page "/fetchdata"
|
||||
|
||||
@using Squirrowse.Web.Data
|
||||
@inject WeatherForecastService ForecastService
|
||||
|
||||
<h1>Weather forecast</h1>
|
||||
|
||||
<p>This component demonstrates fetching data from a service.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Temp. (C)</th>
|
||||
<th>Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
WeatherForecast[] forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
|
||||
}
|
||||
}
|
@ -25,34 +25,22 @@
|
||||
View cast
|
||||
</button>
|
||||
|
||||
<button id="StopViewCast" disabled="@(!IsViewingCastOf(agent.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() => OnStopViewCastClicked(agent.ConnectionId))">
|
||||
<button id="StopViewCast" disabled="@(IsViewingCastOf(agent.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() => OnStopViewCastClicked(agent.ConnectionId))">
|
||||
Stop cast
|
||||
</button>
|
||||
|
||||
<button id="StartRecording" disabled="@(IsViewingCastOf(agent.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() =>StartRecording(agent.ConnectionId))">
|
||||
Stop cast
|
||||
</button>
|
||||
<button id="StartRecording" disabled="@(IsViewingCastOf(agent.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() =>StopRecording(agent.ConnectionId))">
|
||||
Stop cast
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@*<div class="card-body">
|
||||
<div>
|
||||
<h3 class="badge-primary">
|
||||
@agents.AgentName -> @agents.UserType.ToString()
|
||||
</h3>
|
||||
<div style="padding-top:10px">
|
||||
<button id="ViewCast" disabled="@(IsViewingCastOf(agents.AgentName))" class="btn btn-success btn-sm" @onclick="@(() => OnViewCastClicked(agents.ConnectionId))">
|
||||
View cast
|
||||
</button>
|
||||
|
||||
<button id="StopViewCast" disabled="@(!IsViewingCastOf(agents.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() => OnStopViewCastClicked(agents.ConnectionId))">
|
||||
Stop cast
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>*@
|
||||
|
||||
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="card-body">
|
||||
<h3 class="card-header badge-warning">No Cams</h3>
|
||||
@ -65,7 +53,7 @@ else
|
||||
</div>
|
||||
@code{
|
||||
|
||||
private List<User> agents;
|
||||
private List<User> agents=new List<User>();
|
||||
|
||||
HubConnection connection;
|
||||
string imageSource = null;
|
||||
@ -73,46 +61,61 @@ else
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
agents=new List<User>();
|
||||
await _connection.InitConnection(ConnectionType.Server);
|
||||
connection = await _connection.GetConnection();
|
||||
|
||||
connection.On<IAsyncEnumerable<byte[]>>("RecData", OnStreamDataReceived);
|
||||
//agents = await connection.InvokeAsync<string>("GetListOfTypeUserString");
|
||||
//agents = await connection.InvokeAsync<User>("Getasuser");
|
||||
//agents = await connection.InvokeAsync<IAsyncEnumerable<User>>("GetListOfTypeUserAsync",ConnectionType.Client);
|
||||
await foreach (var dupa in connection.StreamAsync<User>("GetListOfTypeUserAsync", ConnectionType.Client))
|
||||
connection.On<byte[]>("RecData", OnStreamDataReceived);
|
||||
|
||||
await foreach (var user in connection.StreamAsync<User>("GetListOfTypeUserAsync", ConnectionType.Client).ConfigureAwait(false))
|
||||
{
|
||||
agents.Add(dupa);
|
||||
agents.Add(user);
|
||||
this.StateHasChanged();
|
||||
}
|
||||
//connection.On<User>("NewUser", NewUser);
|
||||
//connection.On<string>("RemoveScreenCastAgent", RemoveScreenCastAgent);
|
||||
//connection.On<string>("OnStreamDataReceived", OnStreamDataReceived);
|
||||
|
||||
//await connection.StartAsync();
|
||||
}
|
||||
|
||||
|
||||
bool IsViewingCastOf(string agentName)
|
||||
{
|
||||
return agentName == CurrentViewCastAgent;
|
||||
}
|
||||
|
||||
//void NewUser(User agentName)
|
||||
//{
|
||||
// agents.Add(agentName);
|
||||
// StateHasChanged();
|
||||
//}
|
||||
|
||||
async void OnStreamDataReceived(IAsyncEnumerable<byte[]> streamData)
|
||||
async Task StartRecording(string agent)
|
||||
{
|
||||
await foreach (var t in streamData)
|
||||
{
|
||||
var base64 = Convert.ToBase64String(t);
|
||||
imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||
StateHasChanged();
|
||||
await connection.SendAsync("StartRecord");
|
||||
StateHasChanged();
|
||||
}
|
||||
async Task StopRecording(string agent)
|
||||
{
|
||||
await connection.SendAsync("StopRecord");
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
async Task OnStreamDataReceived(byte[] streamData)
|
||||
{
|
||||
//await foreach (var t in streamData)
|
||||
//{
|
||||
// var base64 = Convert.ToBase64String(t);
|
||||
// imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||
// StateHasChanged();
|
||||
//}
|
||||
|
||||
var base64 = Convert.ToBase64String(streamData);
|
||||
imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||
StateHasChanged();
|
||||
|
||||
}
|
||||
async Task OnStreamDataReceivedEn(byte[] streamData)
|
||||
{
|
||||
//await foreach (var t in streamData)
|
||||
//{
|
||||
// var base64 = Convert.ToBase64String(t);
|
||||
// imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||
// StateHasChanged();
|
||||
//}
|
||||
|
||||
var base64 = Convert.ToBase64String(streamData);
|
||||
imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||
StateHasChanged();
|
||||
|
||||
}
|
||||
|
||||
private async Task OnViewCastClicked(string agentName)
|
||||
@ -125,7 +128,7 @@ else
|
||||
private async Task OnStopViewCastClicked(string agentName)
|
||||
{
|
||||
CurrentViewCastAgent = null;
|
||||
await connection.InvokeAsync("Stopstream", agentName);
|
||||
await connection.InvokeAsync("StopStream", agentName);
|
||||
imageSource = null;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
@ -2,4 +2,4 @@
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
||||
Welcome to aws.
|
@ -1,22 +1,179 @@
|
||||
@page "/"
|
||||
@namespace Squirrowse.Web.Pages
|
||||
@namespace squirrowse.web.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Squirrowse.Web</title>
|
||||
<base href="~/" />
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||
<link href="css/site.css" rel="stylesheet" />
|
||||
<script src="jquery/jquery.js"></script>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>squirrowse.web</title>
|
||||
<base href="~/"/>
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="lib/lightgallery/css/lightgallery.css"/>
|
||||
<link href="css/site.css" rel="stylesheet"/>
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
.demo-gallery > ul { margin-bottom: 0; }
|
||||
|
||||
.demo-gallery > ul > li {
|
||||
float: left;
|
||||
margin-bottom: 15px;
|
||||
margin-right: 20px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a {
|
||||
border: 3px solid #FFF;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mostly-customized-scrollbar::-webkit-scrollbar {
|
||||
background-color: #aaa; /* or add it to the track */
|
||||
height: 8px;
|
||||
overflow: auto;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a > img {
|
||||
-moz-transition: -moz-transform 0.15s ease 0s;
|
||||
-o-transition: -o-transform 0.15s ease 0s;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
-webkit-transition: -webkit-transform 0.15s ease 0s;
|
||||
height: 100%;
|
||||
transform: scale3d(1, 1, 1);
|
||||
transition: transform 0.15s ease 0s;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a:hover > img {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a:hover .demo-gallery-poster > img { opacity: 1; }
|
||||
|
||||
.demo-gallery > ul > li a .demo-gallery-poster {
|
||||
-o-transition: background-color 0.15s ease 0s;
|
||||
-webkit-transition: background-color 0.15s ease 0s;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transition: background-color 0.15s ease 0s;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a .demo-gallery-poster > img {
|
||||
-o-transition: opacity 0.3s ease 0s;
|
||||
-webkit-transition: opacity 0.3s ease 0s;
|
||||
left: 50%;
|
||||
margin-left: -10px;
|
||||
margin-top: -10px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transition: opacity 0.3s ease 0s;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a:hover .demo-gallery-poster { background-color: rgba(0, 0, 0, 0.5); }
|
||||
|
||||
.demo-gallery .justified-gallery > a > img {
|
||||
-moz-transition: -moz-transform 0.15s ease 0s;
|
||||
-o-transition: -o-transform 0.15s ease 0s;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
-webkit-transition: -webkit-transform 0.15s ease 0s;
|
||||
height: 100%;
|
||||
transform: scale3d(1, 1, 1);
|
||||
transition: transform 0.15s ease 0s;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.demo-gallery .justified-gallery > a:hover > img {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
|
||||
.demo-gallery .justified-gallery > a:hover .demo-gallery-poster > img { opacity: 1; }
|
||||
|
||||
.demo-gallery .justified-gallery > a .demo-gallery-poster {
|
||||
-o-transition: background-color 0.15s ease 0s;
|
||||
-webkit-transition: background-color 0.15s ease 0s;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transition: background-color 0.15s ease 0s;
|
||||
}
|
||||
|
||||
.demo-gallery .justified-gallery > a .demo-gallery-poster > img {
|
||||
-o-transition: opacity 0.3s ease 0s;
|
||||
-webkit-transition: opacity 0.3s ease 0s;
|
||||
left: 50%;
|
||||
margin-left: -10px;
|
||||
margin-top: -10px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transition: opacity 0.3s ease 0s;
|
||||
}
|
||||
|
||||
.demo-gallery .justified-gallery > a:hover .demo-gallery-poster { background-color: rgba(0, 0, 0, 0.5); }
|
||||
|
||||
.demo-gallery .video .demo-gallery-poster img {
|
||||
height: 48px;
|
||||
margin-left: -24px;
|
||||
margin-top: -24px;
|
||||
opacity: 0.8;
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.demo-gallery.dark > ul > li a { border: 3px solid #04070a; }
|
||||
|
||||
.home .demo-gallery { padding-bottom: 80px; }
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<app>
|
||||
@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
|
||||
</app>
|
||||
<app>
|
||||
<component type="typeof(App)" render-mode="ServerPrerendered"/>
|
||||
</app>
|
||||
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
<div id="blazor-error-ui">
|
||||
<environment include="Staging,Production">
|
||||
An error has occurred. This application may no longer respond until reloaded.
|
||||
</environment>
|
||||
<environment include="Development">
|
||||
An unhandled exception has occurred. See browser dev tools for details.
|
||||
</environment>
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
|
||||
<script src="lib/lightgallery/js/lightgallery-all.js"></script>
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
<script>
|
||||
function galeryJs() {
|
||||
|
||||
$('.lgalery').lightGallery();
|
||||
};
|
||||
|
||||
function colapseD() {
|
||||
$('.collapse').collapse();
|
||||
};
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@ -1,15 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Squirrowse.Web
|
||||
namespace squirrowse.web
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
@ -18,11 +10,10 @@ namespace Squirrowse.Web
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||
{
|
||||
return Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>().UseUrls("http://0.0.0.0:5000"); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:56422",
|
||||
"sslPort": 44381
|
||||
"applicationUrl": "http://192.168.0.13:8000",
|
||||
"sslPort": 443
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
@ -15,13 +15,21 @@
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"Squirrowse.Web": {
|
||||
"squirrowse.web": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:5003;http://localhost:5002",
|
||||
"useSSL": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"applicationUrl": "http://192.168.0.13:8000"
|
||||
},
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"publishAllPorts": true,
|
||||
"useSSL": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
<NavMenu/>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<div class="top-row px-4">
|
||||
<a href="https://docs.microsoft.com/en-us/aspnet/" target="_blank">About</a>
|
||||
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
|
||||
</div>
|
||||
|
||||
<div class="content px-4">
|
||||
@Body
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
<div class="top-row pl-4 navbar navbar-dark">
|
||||
<a class="navbar-brand" href="">Squirrowse.Web</a>
|
||||
<a class="navbar-brand" href="">squirrowse.web</a>
|
||||
<button class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
@ -13,30 +13,26 @@
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="counter">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Counter
|
||||
<NavLink class="nav-link" href="client">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Client
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="fetchdata">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="Hub">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Stream
|
||||
<NavLink class="nav-link" href="galery">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Galery
|
||||
</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
bool collapseNavMenu = true;
|
||||
private bool collapseNavMenu = true;
|
||||
|
||||
string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
|
||||
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
|
||||
|
||||
void ToggleNavMenu()
|
||||
private void ToggleNavMenu()
|
||||
{
|
||||
collapseNavMenu = !collapseNavMenu;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +1,44 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<UserSecretsId>e06d99cb-4df6-41f0-8639-cd34df940830</UserSecretsId>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Squirrowse.Core\Squirrowse.Core.csproj" />
|
||||
<PackageReference Include="CNTK.Deps.OpenCV.Zip" Version="2.8.0-rc0.dev20200201" />
|
||||
<PackageReference Include="DevExpress.Blazor" Version="19.2.4-preview" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.Azure.CognitiveServices.Vision.ComputerVision" Version="6.0.0-dev.20190919.3" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.10" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.2.0.20200208" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.ubuntu.18.04-x64" Version="4.2.0.20200208" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<ProjectReference Include="..\squirrowse.core\squirrowse.core.csproj" />
|
||||
<ProjectReference Include="..\squirrowse.db\squirrowse.db.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<None Update="StaticFiles\haarcascade_frontalface_alt.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StaticFiles\haarcascade_lowerbody.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StaticFiles\haarcascade_upperbody.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties appsettings_1development_1json__JsonSchema="http://json.schemastore.org/asmdef" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
|
||||
</Project>
|
@ -1,18 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Squirrowse.Core;
|
||||
using Squirrowse.Web.Data;
|
||||
using squirrowse.db;
|
||||
using squirrowse.web.Cognitive;
|
||||
using squirrowse.web.Data;
|
||||
|
||||
namespace Squirrowse.Web
|
||||
namespace squirrowse.web
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
@ -28,11 +25,20 @@ namespace Squirrowse.Web
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddRazorPages();
|
||||
|
||||
services.AddServerSideBlazor().AddHubOptions(x=>x.MaximumReceiveMessageSize= 102400000);
|
||||
services.AddCoreModule();
|
||||
services.AddSignalR().AddMessagePackProtocol();
|
||||
services.AddSingleton<WeatherForecastService>();
|
||||
services.AddServerSideBlazor().AddHubOptions(x =>
|
||||
{
|
||||
x.EnableDetailedErrors = true;
|
||||
x.MaximumReceiveMessageSize = short.MaxValue;
|
||||
});
|
||||
|
||||
services.AddSingleton<SaveVideo>();
|
||||
services.AddSingleton<Detection>();
|
||||
services.AddSingleton<IAzureCV, AzureCV>();
|
||||
services.AddSingleton<DbContext>();
|
||||
services.AddSingleton<GaleryService>();
|
||||
services.AddSingleton<Bloob>();
|
||||
services.AddSingleton<VideoQ>();
|
||||
services.AddSignalR(x => x.MaximumReceiveMessageSize = ((int)(int.MaxValue / 2))).AddMessagePackProtocol();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
@ -49,16 +55,17 @@ namespace Squirrowse.Web
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UsePathBase(new PathString("/extra"));
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapBlazorHub();
|
||||
endpoints.MapFallbackToPage("/_Host");
|
||||
endpoints.MapHub<ClientHub>("hub");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,5 +5,5 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.JSInterop
|
||||
@using Squirrowse.Web
|
||||
@using Squirrowse.Web.Shared
|
||||
@using squirrowse.web
|
||||
@using squirrowse.web.Shared
|
@ -1,9 +1,10 @@
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,4 +7,4 @@
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
}
|
@ -1,34 +1,28 @@
|
||||
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
|
||||
|
||||
html, body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
html, body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; }
|
||||
|
||||
a, .btn-link {
|
||||
color: #0366d6;
|
||||
}
|
||||
a, .btn-link { color: #0366d6; }
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
app {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 3.5rem;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
}
|
||||
.main { flex: 1; }
|
||||
|
||||
.main .top-row {
|
||||
background-color: #f7f7f7;
|
||||
@ -36,97 +30,102 @@ app {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.main .top-row > a {
|
||||
.main .top-row > a, .main .top-row .btn-link {
|
||||
margin-left: 1.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
||||
.main .top-row a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.sidebar .top-row {
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
.sidebar { background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); }
|
||||
|
||||
.sidebar .navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.sidebar .top-row { background-color: rgba(0, 0, 0, 0.4); }
|
||||
|
||||
.sidebar .navbar-brand { font-size: 1.1rem; }
|
||||
|
||||
.sidebar .oi {
|
||||
width: 2rem;
|
||||
font-size: 1.1rem;
|
||||
vertical-align: text-top;
|
||||
top: -2px;
|
||||
vertical-align: text-top;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
.sidebar .nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
.sidebar .nav-item:first-of-type { padding-top: 1rem; }
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
.sidebar .nav-item:last-of-type { padding-bottom: 1rem; }
|
||||
|
||||
.nav-item a {
|
||||
color: #d7d7d7;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
.sidebar .nav-item a {
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
color: #d7d7d7;
|
||||
display: flex;
|
||||
height: 3rem;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
.nav-item a.active {
|
||||
background-color: rgba(255,255,255,0.25);
|
||||
.sidebar .nav-item a.active {
|
||||
background-color: rgba(255, 255, 255, 0.25);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item a:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1.1rem;
|
||||
}
|
||||
|
||||
.navbar-toggler {
|
||||
.sidebar .nav-item a:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.valid.modified:not([type=checkbox]) {
|
||||
outline: 1px solid #26b050;
|
||||
.content { padding-top: 1.1rem; }
|
||||
|
||||
.navbar-toggler { background-color: rgba(255, 255, 255, 0.1); }
|
||||
|
||||
.valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; }
|
||||
|
||||
.invalid { outline: 1px solid red; }
|
||||
|
||||
.validation-message { color: red; }
|
||||
|
||||
#blazor-error-ui {
|
||||
background: lightyellow;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
display: none;
|
||||
left: 0;
|
||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
outline: 1px solid red;
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
color: red;
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.main .top-row {
|
||||
display: none;
|
||||
}
|
||||
.main .top-row:not(.auth) { display: none; }
|
||||
|
||||
.main .top-row.auth { justify-content: space-between; }
|
||||
|
||||
.main .top-row a, .main .top-row .btn-link { margin-left: 0; }
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
app {
|
||||
flex-direction: row;
|
||||
}
|
||||
app { flex-direction: row; }
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.main .top-row {
|
||||
@ -139,12 +138,10 @@ app {
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
.navbar-toggler { display: none; }
|
||||
|
||||
.sidebar .collapse {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +1,15 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29411.108
|
||||
VisualStudioVersion = 16.0.29806.167
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squirrowse.Service", "Squirrowse.Service\Squirrowse.Service.csproj", "{8C085621-BAAA-4E96-B027-561BC18751EE}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "squirrowse.web", "squirrowse.web\squirrowse.web.csproj", "{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squirrowse.Client", "Squirrowse.Client\Squirrowse.Client.csproj", "{558A5917-6AD3-4C40-ACA1-EE3B8B8927C8}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "squirrowse.db", "squirrowse.db\squirrowse.db.csproj", "{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squirrowse.Core", "Squirrowse.Core\Squirrowse.Core.csproj", "{D0989FCC-484E-4ADB-BA5E-1020894F9C09}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "squirrowse.core", "squirrowse.core\squirrowse.core.csproj", "{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BB569A06-F4D1-4927-87AB-86C4BD2AFBC5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squirrowse.Core.Tests", "Squirrowse.Core.Tests\Squirrowse.Core.Tests.csproj", "{CFA96677-EAA7-4871-AAD8-E6336973366F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squirrowse.Web", "Squirrowse.Web\Squirrowse.Web.csproj", "{5FEF6EDF-3327-48B1-9298-26A24D023924}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{D0989FCC-484E-4ADB-BA5E-1020894F9C09} = {D0989FCC-484E-4ADB-BA5E-1020894F9C09}
|
||||
EndProjectSection
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "squirrowse.client", "squirrowse.client\squirrowse.client.csproj", "{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -24,34 +17,27 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8C085621-BAAA-4E96-B027-561BC18751EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C085621-BAAA-4E96-B027-561BC18751EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C085621-BAAA-4E96-B027-561BC18751EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C085621-BAAA-4E96-B027-561BC18751EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{558A5917-6AD3-4C40-ACA1-EE3B8B8927C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{558A5917-6AD3-4C40-ACA1-EE3B8B8927C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{558A5917-6AD3-4C40-ACA1-EE3B8B8927C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{558A5917-6AD3-4C40-ACA1-EE3B8B8927C8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D0989FCC-484E-4ADB-BA5E-1020894F9C09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D0989FCC-484E-4ADB-BA5E-1020894F9C09}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D0989FCC-484E-4ADB-BA5E-1020894F9C09}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D0989FCC-484E-4ADB-BA5E-1020894F9C09}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CFA96677-EAA7-4871-AAD8-E6336973366F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CFA96677-EAA7-4871-AAD8-E6336973366F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CFA96677-EAA7-4871-AAD8-E6336973366F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CFA96677-EAA7-4871-AAD8-E6336973366F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5FEF6EDF-3327-48B1-9298-26A24D023924}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5FEF6EDF-3327-48B1-9298-26A24D023924}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5FEF6EDF-3327-48B1-9298-26A24D023924}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5FEF6EDF-3327-48B1-9298-26A24D023924}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{CFA96677-EAA7-4871-AAD8-E6336973366F} = {BB569A06-F4D1-4927-87AB-86C4BD2AFBC5}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1CC5C3B8-3825-4EB5-ACFF-73B4CAC8945D}
|
||||
SolutionGuid = {8CE6F2C5-E801-4DB6-8A77-7CA7DB88E070}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
35
squirrowse.client/Connection.cs
Normal file
35
squirrowse.client/Connection.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
|
||||
namespace squirrowse.client
|
||||
{
|
||||
public class Connection
|
||||
{
|
||||
public string ip { get; set; }
|
||||
private readonly Webcam _cam;
|
||||
public Connection()
|
||||
{
|
||||
_cam = new Webcam();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async IAsyncEnumerable<byte[]> clientStreamData()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
var data = _cam.GetBitmap();
|
||||
await Task.Delay(100);
|
||||
yield return data;
|
||||
|
||||
}
|
||||
//After the for loop has completed and the local function exits the stream completion will be sent.
|
||||
}
|
||||
|
||||
}
|
||||
}
|
59
squirrowse.client/ConnectionManager.cs
Normal file
59
squirrowse.client/ConnectionManager.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace squirrowse.client
|
||||
{
|
||||
public class ConnectionManager : IConnectionManager
|
||||
{
|
||||
private readonly HubConnection _connection;
|
||||
public bool Connected;
|
||||
|
||||
public ConnectionManager(string url, int port)
|
||||
{
|
||||
_connection = new HubConnectionBuilder()
|
||||
.WithUrl($"{url}:{port}/hub")
|
||||
.WithAutomaticReconnect()
|
||||
.AddMessagePackProtocol()
|
||||
.Build();
|
||||
}
|
||||
|
||||
public async Task<HubConnection> GetConnection()
|
||||
{
|
||||
if (Connected) return _connection;
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
public async Task InitConnection()
|
||||
{
|
||||
if (_connection.State == HubConnectionState.Connected) return;
|
||||
await _connection.StartAsync();
|
||||
Connected = true;
|
||||
}
|
||||
|
||||
public async Task Disconnect()
|
||||
{
|
||||
if (_connection.State == HubConnectionState.Disconnected) throw new Exception();
|
||||
await _connection.StopAsync();
|
||||
Connected = false;
|
||||
}
|
||||
|
||||
public bool IsConnected()
|
||||
{
|
||||
return Connected;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IConnectionManager
|
||||
{
|
||||
Task<HubConnection> GetConnection();
|
||||
Task InitConnection();
|
||||
Task Disconnect();
|
||||
|
||||
bool IsConnected();
|
||||
}
|
||||
}
|
27
squirrowse.client/Program.cs
Normal file
27
squirrowse.client/Program.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
namespace squirrowse.client
|
||||
{
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||
{
|
||||
return Host.CreateDefaultBuilder(args)
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
services.AddHostedService<Worker>();
|
||||
services.AddSingleton<IConnectionManager>(x =>
|
||||
new ConnectionManager("http://squirrowse.azurewebsites.net", 80)); //keep as transient for now
|
||||
|
||||
// new ConnectionManager("http://192.168.0.13", 5000)); //keep as transient for now
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
85
squirrowse.client/WebCam.cs
Normal file
85
squirrowse.client/WebCam.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using OpenCvSharp;
|
||||
using OpenCvSharp.Extensions;
|
||||
|
||||
namespace squirrowse.client
|
||||
{
|
||||
public class Webcam
|
||||
{
|
||||
private static VideoCapture capture;
|
||||
private static Mat frame;
|
||||
private static Byte[] image;
|
||||
private static Thread camera;
|
||||
private static bool isCameraRunning;
|
||||
private readonly bool imagetakinginprogress = false;
|
||||
|
||||
public Webcam(bool AutoActivate = true)
|
||||
{
|
||||
if (AutoActivate) Initalize();
|
||||
}
|
||||
|
||||
public void Initalize()
|
||||
{
|
||||
CaptureCamera();
|
||||
isCameraRunning = true;
|
||||
}
|
||||
|
||||
private void CaptureCamera()
|
||||
{
|
||||
camera = new Thread(CaptureCameraCallback);
|
||||
camera.Start();
|
||||
}
|
||||
|
||||
private void CaptureCameraCallback()
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
if (!isCameraRunning) return;
|
||||
frame = new Mat();
|
||||
capture = new VideoCapture(0);
|
||||
capture.Open(0);
|
||||
if (!capture.IsOpened()) return;
|
||||
while (isCameraRunning)
|
||||
{
|
||||
capture.Read(frame);
|
||||
image = frame.ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetBitmap()
|
||||
{
|
||||
if (!isCameraRunning) throw new Exception("Cannot take picutre if the camera is not initalized!");
|
||||
while (imagetakinginprogress)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
return image;
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
return image;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Deinitialize()
|
||||
{
|
||||
camera.Abort();
|
||||
capture.Release();
|
||||
isCameraRunning = false;
|
||||
}
|
||||
|
||||
~Webcam()
|
||||
{
|
||||
Deinitialize();
|
||||
capture.Dispose();
|
||||
frame.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
41
squirrowse.client/Worker.cs
Normal file
41
squirrowse.client/Worker.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace squirrowse.client
|
||||
{
|
||||
public class Worker : IHostedService
|
||||
{
|
||||
private readonly ILogger<Worker> logger;
|
||||
private readonly IConnectionManager _connectionManager;
|
||||
private Connection con =new Connection();
|
||||
public Worker(ILogger<Worker> logger, IConnectionManager connectionManager)
|
||||
{
|
||||
this.logger = logger;
|
||||
_connectionManager = connectionManager;
|
||||
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _connectionManager.InitConnection();
|
||||
|
||||
//var d = _connectionManager.GetConnection();
|
||||
if (_connectionManager.IsConnected())
|
||||
{
|
||||
var d =await _connectionManager.GetConnection();
|
||||
await d.SendAsync("UploadStream", con.clientStreamData());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _connectionManager.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
17
squirrowse.client/squirrowse.client.csproj
Normal file
17
squirrowse.client/squirrowse.client.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.2" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.2.0.20200208" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.2.0.20200208" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
101
squirrowse.core/Common/ConcurentFixedSizeQueue.cs
Normal file
101
squirrowse.core/Common/ConcurentFixedSizeQueue.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace squirrowse.web.Common
|
||||
{
|
||||
public class ConcurrentFixedSizeQueue<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>, ICollection
|
||||
{
|
||||
private readonly ConcurrentQueue<T> m_concurrentQueue;
|
||||
private readonly int m_maxSize;
|
||||
|
||||
public ConcurrentFixedSizeQueue(int maxSize) : this(Array.Empty<T>(), maxSize)
|
||||
{
|
||||
}
|
||||
|
||||
public ConcurrentFixedSizeQueue(IEnumerable<T> initialCollection, int maxSize)
|
||||
{
|
||||
if (initialCollection == null) throw new ArgumentNullException(nameof(initialCollection));
|
||||
|
||||
m_concurrentQueue = new ConcurrentQueue<T>(initialCollection);
|
||||
m_maxSize = maxSize;
|
||||
}
|
||||
|
||||
public bool IsEmpty => m_concurrentQueue.IsEmpty;
|
||||
|
||||
public int Count => m_concurrentQueue.Count;
|
||||
|
||||
public void CopyTo(T[] array, int index)
|
||||
{
|
||||
m_concurrentQueue.CopyTo(array, index);
|
||||
}
|
||||
|
||||
public T[] ToArray()
|
||||
{
|
||||
return m_concurrentQueue.ToArray();
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return m_concurrentQueue.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
// Explicit ICollection implementations.
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
((ICollection) m_concurrentQueue).CopyTo(array, index);
|
||||
}
|
||||
|
||||
object ICollection.SyncRoot => ((ICollection) m_concurrentQueue).SyncRoot;
|
||||
bool ICollection.IsSynchronized => ((ICollection) m_concurrentQueue).IsSynchronized;
|
||||
|
||||
// Explicit IProducerConsumerCollection<T> implementations.
|
||||
bool IProducerConsumerCollection<T>.TryAdd(T item)
|
||||
{
|
||||
return ((IProducerConsumerCollection<T>) m_concurrentQueue).TryAdd(item);
|
||||
}
|
||||
|
||||
bool IProducerConsumerCollection<T>.TryTake(out T item)
|
||||
{
|
||||
return ((IProducerConsumerCollection<T>) m_concurrentQueue).TryTake(out item);
|
||||
}
|
||||
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
m_concurrentQueue.Enqueue(item);
|
||||
|
||||
if (m_concurrentQueue.Count > m_maxSize) m_concurrentQueue.TryDequeue(out var result);
|
||||
}
|
||||
|
||||
public void TryPeek(out T result)
|
||||
{
|
||||
m_concurrentQueue.TryPeek(out result);
|
||||
}
|
||||
|
||||
public bool TryDequeue(out T result)
|
||||
{
|
||||
return m_concurrentQueue.TryDequeue(out result);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return m_concurrentQueue.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return m_concurrentQueue.Equals(obj);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return m_concurrentQueue.ToString();
|
||||
}
|
||||
}
|
||||
}
|
35
squirrowse.core/Frame.cs
Normal file
35
squirrowse.core/Frame.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using LiteDB;
|
||||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace squirrowse.core
|
||||
{
|
||||
public class Frame
|
||||
{
|
||||
public Frame()
|
||||
{
|
||||
}
|
||||
|
||||
public Frame(Mat frameMat, IList<DetectedObject> objects, Uri src)
|
||||
{
|
||||
FrameMat = frameMat;
|
||||
Objects = objects;
|
||||
ImgSrc = src;
|
||||
}
|
||||
|
||||
[BsonIgnore] public Mat FrameMat { get; set; }
|
||||
|
||||
public IList<DetectedObject> Objects { get; set; }
|
||||
|
||||
public Uri ImgSrc { get; set; }
|
||||
|
||||
public Mat CopyMat(Mat xd)
|
||||
{
|
||||
var xd2 = new Mat();
|
||||
xd.CopyTo(xd2);
|
||||
return xd2;
|
||||
}
|
||||
}
|
||||
}
|
17
squirrowse.core/squirrowse.core.csproj
Normal file
17
squirrowse.core/squirrowse.core.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LiteDB" Version="5.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.Azure.CognitiveServices.Vision.ComputerVision" Version="6.0.0-dev.20190919.3" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.2.0.20200208" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.ubuntu.18.04-x64" Version="4.2.0.20200208" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
32
squirrowse.db/Bloob.cs
Normal file
32
squirrowse.db/Bloob.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using Azure.Storage.Blobs;
|
||||
|
||||
namespace squirrowse.db
|
||||
{
|
||||
public class Bloob
|
||||
{
|
||||
private readonly BlobServiceClient _blobServiceClient;
|
||||
|
||||
public BlobContainerClient Container;
|
||||
|
||||
public Bloob()
|
||||
{
|
||||
_blobServiceClient =
|
||||
new BlobServiceClient(
|
||||
"DefaultEndpointsProtocol=https;AccountName=squirrowse;AccountKey=/S09Er70NmQ6vNwJU0eVG0pbV5DklBx8vdp4M28dEfr0ZRmSzd5B/STrzDTfkbxg4BcN+rRu93pRowC/4Ys48A==;EndpointSuffix=core.windows.net");
|
||||
Container = CreateImgBloob("squirrowseimg");
|
||||
}
|
||||
|
||||
private BlobContainerClient CreateImgBloob(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _blobServiceClient.CreateBlobContainer(name);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return _blobServiceClient.GetBlobContainerClient(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
squirrowse.db/DbContext.cs
Normal file
32
squirrowse.db/DbContext.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using LiteDB;
|
||||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
|
||||
using squirrowse.core;
|
||||
|
||||
namespace squirrowse.db
|
||||
{
|
||||
public class DbContext
|
||||
{
|
||||
private readonly LiteDatabase _context;
|
||||
|
||||
public DbContext()
|
||||
{
|
||||
//BsonMapper.Global.Entity<Frame>().DbRef(x => x.Objects);
|
||||
//BsonMapper.Global.Entity<DetectedObject>().DbRef(x => x.ObjectProperty);
|
||||
_context = new LiteDatabase("db.db");
|
||||
_context.GetCollection<Frame>();
|
||||
_context.GetCollection<DetectResult>();
|
||||
_context.GetCollection<DetectedObject>();
|
||||
|
||||
|
||||
BsonMapper.Global.IncludeFields = true;
|
||||
using (GetRepository)
|
||||
{
|
||||
GetRepository = _context;
|
||||
}
|
||||
}
|
||||
|
||||
public ILiteCollection<Frame> GetFrameCollection => _context.GetCollection<Frame>();
|
||||
|
||||
public LiteDatabase GetRepository { get; }
|
||||
}
|
||||
}
|
17
squirrowse.db/squirrowse.db.csproj
Normal file
17
squirrowse.db/squirrowse.db.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.3.0" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.3" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.ubuntu.18.04-x64" Version="4.2.0.20200208" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\squirrowse.core\squirrowse.core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
43
squirrowse.sln
Normal file
43
squirrowse.sln
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29806.167
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "squirrowse.web", "squirrowse.web\squirrowse.web.csproj", "{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "squirrowse.db", "squirrowse.db\squirrowse.db.csproj", "{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "squirrowse.core", "squirrowse.core\squirrowse.core.csproj", "{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "squirrowse.client", "squirrowse.client\squirrowse.client.csproj", "{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8A3C08CE-2DB6-4339-9A72-6EB58AD2300F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{322D1CFC-AEC6-4C8A-9561-8CB25F3C8A4F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0C908BE8-729C-4DCA-92DE-07FB7346EBB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{89E3C9E7-94E5-4976-97C0-0703F6C9DF49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8CE6F2C5-E801-4DB6-8A77-7CA7DB88E070}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
12
squirrowse.web/.config/dotnet-tools.json
Normal file
12
squirrowse.web/.config/dotnet-tools.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "3.1.1",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
10
squirrowse.web/App.razor
Normal file
10
squirrowse.web/App.razor
Normal file
@ -0,0 +1,10 @@
|
||||
<Router AppAssembly="@typeof(Program).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
</Found>
|
||||
<NotFound>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p>Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
26
squirrowse.web/ClientHub.cs
Normal file
26
squirrowse.web/ClientHub.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using squirrowse.web.Data;
|
||||
|
||||
namespace squirrowse.web
|
||||
{
|
||||
public class ClientHub : Hub
|
||||
{
|
||||
private readonly VideoQ q;
|
||||
|
||||
public ClientHub(VideoQ q)
|
||||
{
|
||||
this.q = q;
|
||||
}
|
||||
public async Task UploadStream(IAsyncEnumerable<byte[]> stream)
|
||||
{
|
||||
await foreach (var frame in stream)
|
||||
{
|
||||
q._framebuffer.Enqueue(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
64
squirrowse.web/Cognitive/AzureCV.cs
Normal file
64
squirrowse.web/Cognitive/AzureCV.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Azure.Storage.Blobs.Models;
|
||||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
|
||||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
|
||||
using OpenCvSharp;
|
||||
using squirrowse.core;
|
||||
using squirrowse.db;
|
||||
|
||||
namespace squirrowse.web.Cognitive
|
||||
{
|
||||
public class AzureCV : IAzureCV
|
||||
{
|
||||
private readonly Bloob _blob;
|
||||
private readonly ComputerVisionClient _client;
|
||||
private readonly DbContext _db;
|
||||
|
||||
public AzureCV(DbContext db, Bloob blob)
|
||||
{
|
||||
_blob = blob;
|
||||
_db = db;
|
||||
_client = new ComputerVisionClient(new ApiKeyServiceClientCredentials("3bac1a140d914fe98300ed1d2ddab5f1"))
|
||||
{
|
||||
Endpoint =
|
||||
"https://squirrowse.cognitiveservices.azure.com/"
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<DetectResult> GetObjects(Mat frame)
|
||||
{
|
||||
var response = await _client.DetectObjectsInStreamAsync(frame.ToMemoryStream());
|
||||
var blobref =
|
||||
_blob.Container.GetBlobClient(
|
||||
$"{DateTime.Now.ToShortDateString()}-{DateTime.Now.ToLongTimeString()}.png");
|
||||
|
||||
await blobref.UploadAsync(frame.ToMemoryStream(), new BlobHttpHeaders {ContentType = "image/png"});
|
||||
|
||||
var t = new Frame(frame, response.Objects, blobref.Uri);
|
||||
_db.GetFrameCollection.Insert(t);
|
||||
return response;
|
||||
}
|
||||
|
||||
public Task<Mat> DrawResults(Mat frame, DetectResult results)
|
||||
{
|
||||
foreach (var result in results.Objects)
|
||||
{
|
||||
Cv2.PutText(frame, result.ObjectProperty.ToUpper(),
|
||||
new Point(result.Rectangle.X, result.Rectangle.Y + result.Rectangle.H * 0.9),
|
||||
HersheyFonts.HersheyComplex, 0.9f, Scalar.Yellow);
|
||||
|
||||
frame.Rectangle(
|
||||
new Rect(result.Rectangle.X, result.Rectangle.Y, result.Rectangle.W, result.Rectangle.H),
|
||||
Scalar.White, 2);
|
||||
}
|
||||
|
||||
return Task.FromResult(frame);
|
||||
}
|
||||
|
||||
public async Task<ImageDescription> GetDescription(Mat frame)
|
||||
{
|
||||
return await _client.DescribeImageInStreamAsync(frame.ToMemoryStream());
|
||||
}
|
||||
}
|
||||
}
|
12
squirrowse.web/Cognitive/IAzureCV.cs
Normal file
12
squirrowse.web/Cognitive/IAzureCV.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace squirrowse.web.Cognitive
|
||||
{
|
||||
public interface IAzureCV
|
||||
{
|
||||
Task<DetectResult> GetObjects(Mat frame);
|
||||
Task<Mat> DrawResults(Mat frame, DetectResult result);
|
||||
}
|
||||
}
|
96
squirrowse.web/Data/Detection.cs
Normal file
96
squirrowse.web/Data/Detection.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace squirrowse.web.Data
|
||||
{
|
||||
public class Filters
|
||||
{
|
||||
public Filters(bool face, bool lowerBody, bool upperBody)
|
||||
{
|
||||
Face = face;
|
||||
LowerBody = lowerBody;
|
||||
UpperBody = upperBody;
|
||||
}
|
||||
|
||||
public bool Face { get; set; }
|
||||
public bool LowerBody { get; set; }
|
||||
public bool UpperBody { get; set; }
|
||||
}
|
||||
|
||||
public class Detection : IDetection
|
||||
{
|
||||
private readonly CascadeClassifier CascadeFace = new CascadeClassifier(
|
||||
@"./StaticFiles/haarcascade_frontalface_alt.xml");
|
||||
|
||||
private readonly CascadeClassifier CascadeLowerBody = new CascadeClassifier(
|
||||
@"./StaticFiles/haarcascade_lowerbody.xml");
|
||||
|
||||
private readonly CascadeClassifier CascadeUpperBody = new CascadeClassifier(
|
||||
@"./StaticFiles/haarcascade_upperbody.xml");
|
||||
|
||||
public Mat DetectTypes(Mat frame, Filters filter)
|
||||
{
|
||||
if (frame == null || frame.IsDisposed || frame.Empty()) return new Mat();
|
||||
var grayImage = new Mat();
|
||||
Cv2.CvtColor(frame, grayImage, ColorConversionCodes.BGRA2GRAY);
|
||||
Cv2.EqualizeHist(grayImage, grayImage);
|
||||
var listtodraw = new List<Rect>();
|
||||
var rnd = new Random();
|
||||
var color = Scalar.FromRgb(rnd.Next(200, 255), rnd.Next(200, 255), rnd.Next(200, 255));
|
||||
if (filter.Face) listtodraw.AddRange(FaceDetection(frame));
|
||||
if (filter.LowerBody) listtodraw.AddRange(LowerBodyDetect(frame));
|
||||
if (filter.UpperBody) listtodraw.AddRange(UpperBodyDetect(frame));
|
||||
foreach (var faceRect in listtodraw)
|
||||
{
|
||||
var detectedFaceImage = new Mat(frame, faceRect);
|
||||
|
||||
//yield return faceRect;
|
||||
|
||||
Cv2.Rectangle(frame, faceRect, color, 3);
|
||||
|
||||
|
||||
var detectedFaceGrayImage = new Mat();
|
||||
Cv2.CvtColor(detectedFaceImage, detectedFaceGrayImage, ColorConversionCodes.BGRA2GRAY);
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
public IEnumerable<Rect> FaceDetection(Mat frame)
|
||||
{
|
||||
var faces = CascadeFace.DetectMultiScale(
|
||||
frame,
|
||||
1.1,
|
||||
2,
|
||||
HaarDetectionType.DoRoughSearch | HaarDetectionType.ScaleImage,
|
||||
new Size(30, 30)
|
||||
);
|
||||
foreach (var faceRect in faces) yield return faceRect;
|
||||
}
|
||||
|
||||
public IEnumerable<Rect> UpperBodyDetect(Mat frame)
|
||||
{
|
||||
var faces = CascadeUpperBody.DetectMultiScale(
|
||||
frame,
|
||||
1.1,
|
||||
3,
|
||||
HaarDetectionType.DoRoughSearch | HaarDetectionType.ScaleImage,
|
||||
new Size(30, 30));
|
||||
|
||||
foreach (var faceRect in faces) yield return faceRect;
|
||||
}
|
||||
|
||||
public IEnumerable<Rect> LowerBodyDetect(Mat frame)
|
||||
{
|
||||
var faces = CascadeLowerBody.DetectMultiScale(
|
||||
frame,
|
||||
1.1,
|
||||
3,
|
||||
HaarDetectionType.DoRoughSearch | HaarDetectionType.ScaleImage,
|
||||
new Size(30, 30));
|
||||
|
||||
foreach (var faceRect in faces) yield return faceRect;
|
||||
}
|
||||
}
|
||||
}
|
75
squirrowse.web/Data/GaleryService.cs
Normal file
75
squirrowse.web/Data/GaleryService.cs
Normal file
@ -0,0 +1,75 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LiteDB;
|
||||
using squirrowse.core;
|
||||
using squirrowse.db;
|
||||
|
||||
namespace squirrowse.web.Data
|
||||
{
|
||||
public class GaleryService
|
||||
{
|
||||
private readonly LiteDatabase db;
|
||||
|
||||
public GaleryService(DbContext db)
|
||||
{
|
||||
this.db = db.GetRepository;
|
||||
}
|
||||
|
||||
public async Task<List<string>> tags()
|
||||
{
|
||||
var tlist = new List<string>();
|
||||
// using var db = new LiteDatabase("db.db");
|
||||
var t = db.GetCollection<Frame>();
|
||||
|
||||
foreach (var frame in t.FindAll().Where(x => x.Objects != null))
|
||||
{
|
||||
var te = frame.Objects.Select(x => x.ObjectProperty).Distinct();
|
||||
tlist.AddRange(te);
|
||||
}
|
||||
|
||||
return tlist.Distinct().ToList();
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, List<Frame>>> galeryEntireView()
|
||||
{
|
||||
var tags = await this.tags();
|
||||
// using var db = new LiteDatabase("db.db");
|
||||
var t = db.GetCollection<Frame>();
|
||||
var d = new Dictionary<string, List<Frame>>();
|
||||
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
var t1 = t.Find(frame => frame.Objects != null);
|
||||
var t2 = t1.Where(x => x.Objects.Any(y => y.ObjectProperty == tag));
|
||||
d.Add(tag, t2.ToList());
|
||||
}
|
||||
|
||||
//var temp = t.Query().Select(x => x.Objects.Where().ToArray();
|
||||
|
||||
// t.Find(x => x.Objects.Any(y => y.ObjectProperty == tag)).ForEach(x => { d.Add(tag, x); });
|
||||
//d.Add(tag,temp);
|
||||
return d;
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, List<Frame>>> galerViewbyTag(List<string> tags)
|
||||
{
|
||||
// using var db = new LiteDatabase("db.db");
|
||||
var t = db.GetCollection<Frame>();
|
||||
var d = new Dictionary<string, List<Frame>>();
|
||||
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
var t1 = t.Find(frame => frame.Objects != null);
|
||||
var t2 = t1.Where(x => x.Objects.Any(y => y.ObjectProperty == tag));
|
||||
d.Add(tag, t2.ToList());
|
||||
}
|
||||
|
||||
//var temp = t.Query().Select(x => x.Objects.Where().ToArray();
|
||||
|
||||
// t.Find(x => x.Objects.Any(y => y.ObjectProperty == tag)).ForEach(x => { d.Add(tag, x); });
|
||||
//d.Add(tag,temp);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
13
squirrowse.web/Data/IDetection.cs
Normal file
13
squirrowse.web/Data/IDetection.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace squirrowse.web.Data
|
||||
{
|
||||
public interface IDetection
|
||||
{
|
||||
Mat DetectTypes(Mat frame, Filters filter);
|
||||
IEnumerable<Rect> FaceDetection(Mat frame);
|
||||
IEnumerable<Rect> UpperBodyDetect(Mat frame);
|
||||
IEnumerable<Rect> LowerBodyDetect(Mat frame);
|
||||
}
|
||||
}
|
10
squirrowse.web/Data/ISaveVideo.cs
Normal file
10
squirrowse.web/Data/ISaveVideo.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace squirrowse.web.Data
|
||||
{
|
||||
public interface ISaveVideo
|
||||
{
|
||||
Task SaveData(IAsyncEnumerable<byte[]> stream);
|
||||
}
|
||||
}
|
24
squirrowse.web/Data/SaveVideo.cs
Normal file
24
squirrowse.web/Data/SaveVideo.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace squirrowse.web.Data
|
||||
{
|
||||
public class SaveVideo : ISaveVideo
|
||||
{
|
||||
public async Task SaveData(IAsyncEnumerable<byte[]> stream)
|
||||
{
|
||||
var videoname = DateTime.UtcNow.ToShortDateString();
|
||||
var output = new VideoWriter(videoname, FourCC.FromFourCCValues(FourCCValues.DIVX), 24.998,
|
||||
new Size(640, 480));
|
||||
|
||||
await foreach (var b in stream)
|
||||
{
|
||||
await Task.Delay(1000 / 33);
|
||||
output.Write(Cv2.ImDecode(b, ImreadModes.Unchanged));
|
||||
// await Task.Delay(1000 / 33);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
squirrowse.web/Data/VideoQ.cs
Normal file
21
squirrowse.web/Data/VideoQ.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using OpenCvSharp;
|
||||
using squirrowse.web.Common;
|
||||
|
||||
namespace squirrowse.web.Data
|
||||
{
|
||||
public class VideoQ
|
||||
{
|
||||
public ConcurrentFixedSizeQueue<byte[]> _framebuffer = new ConcurrentFixedSizeQueue<byte[]>(33);
|
||||
|
||||
public Mat getFrame()
|
||||
{
|
||||
_framebuffer.TryPeek(out byte[] t);
|
||||
return Cv2.ImDecode(t, ImreadModes.Color);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
7
squirrowse.web/NuGet.Config
Normal file
7
squirrowse.web/NuGet.Config
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
<add key="devexpress" value="https://nuget.devexpress.com/ABUfBvYl5nEk34zibEAYwSnHnPjgCvnCPvQjGXho1rjvWetBmz/api" />
|
||||
</packageSources>
|
||||
</configuration>
|
110
squirrowse.web/Pages/Client.razor
Normal file
110
squirrowse.web/Pages/Client.razor
Normal file
@ -0,0 +1,110 @@
|
||||
@page "/client"
|
||||
@using DevExpress.Blazor
|
||||
@using OpenCvSharp
|
||||
@using squirrowse.core
|
||||
@using squirrowse.web.Cognitive
|
||||
@using squirrowse.web.Common
|
||||
@using squirrowse.web.Data
|
||||
|
||||
<h1>live</h1>
|
||||
|
||||
<img src="@_imgSrc" />
|
||||
|
||||
<img src="@_tempcogni" />
|
||||
|
||||
<div style="padding-top: 10px">
|
||||
<button id="Save" class="btn btn-success btn-sm" @onclick="() => GetDataFromAzure()">
|
||||
Azure cognitive
|
||||
</button>
|
||||
</div>
|
||||
<div style="padding-top: 10px">
|
||||
</div>
|
||||
<div class="card demo-card ju" style="width: 18rem;">
|
||||
<ul class="list-group list-group-flush bg-white text-dark" style="border: none">
|
||||
<li class="list-group-item d-flex justify-content-between" style="background-color: transparent; color: inherit;">
|
||||
<DxCheckBox CheckType="CheckType.Switch" LabelPosition="@LabelPosition.Left" style="width: 100%" Checked="@fetchDataFromAzure" CheckedChanged="@Update(v => fetchDataFromAzure = v)">Fetch Data from azure</DxCheckBox>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between" style="background-color: transparent; color: inherit;">
|
||||
<DxCheckBox CheckType="CheckType.Switch" LabelPosition="@LabelPosition.Left" style="width: 100%" Checked="@filter.Face" CheckedChanged="@Update(v => filter.Face = v)">Face</DxCheckBox>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between" style="background-color: transparent; color: inherit;">
|
||||
<DxCheckBox CheckType="CheckType.Switch" LabelPosition="@LabelPosition.Left" style="width: 100%" Checked="@filter.UpperBody" CheckedChanged="@Update(v => filter.UpperBody = v)">Upper Body</DxCheckBox>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between" style="background-color: transparent; color: inherit;">
|
||||
<DxCheckBox CheckType="CheckType.Switch" LabelPosition="@LabelPosition.Left" style="width: 100%" Checked="@filter.LowerBody" CheckedChanged="@Update(v => filter.LowerBody = v)">Lower Body</DxCheckBox>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@inject SaveVideo save
|
||||
@inject IAzureCV azureCv
|
||||
@inject VideoQ Video
|
||||
@inject Detection detect
|
||||
|
||||
@code { private readonly Filters filter = new Filters(false, false, false);
|
||||
private string _imgSrc;
|
||||
private string _tempcogni;
|
||||
private byte[] buffer;
|
||||
private bool fetchDataFromAzure = true;
|
||||
|
||||
private readonly Frame Frametest = new Frame();
|
||||
|
||||
private Mat tempory = new Mat();
|
||||
|
||||
public Action<bool> Update(Action<bool> set)
|
||||
{
|
||||
return v =>
|
||||
{
|
||||
set(v);
|
||||
InvokeAsync(StateHasChanged);
|
||||
};
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
using var temp = new Mat(480, 640, MatType.CV_8UC3, new Scalar(0, 0, 100));
|
||||
|
||||
Cv2.PutText(temp, "No clients".ToUpper(),
|
||||
new Point(240, 320),
|
||||
HersheyFonts.HersheyComplex, 0.9f, Scalar.Yellow);
|
||||
var base64T = Convert.ToBase64String(temp.ToBytes());
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
using var frame = Video.getFrame();
|
||||
tempory = Frametest.CopyMat(frame);
|
||||
var face = detect.DetectTypes(frame, filter);
|
||||
buffer = face.ToBytes();
|
||||
var base64 = Convert.ToBase64String(buffer);
|
||||
_imgSrc = $"data:image/gif;base64,{base64}";
|
||||
Cv2.WaitKey(1);
|
||||
await Task.Delay(1000 / 33);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_imgSrc = $"data:image/gif;base64,{base64T}";
|
||||
await Task.Delay(1000 / 33);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async Task GetDataFromAzure()
|
||||
{
|
||||
while (fetchDataFromAzure)
|
||||
{
|
||||
var azrespons = await azureCv.GetObjects(tempory);
|
||||
var azureFrame = azureCv.DrawResults(tempory, azrespons);
|
||||
var b_tempcogni = Convert.ToBase64String(azureFrame.Result.ToBytes());
|
||||
_tempcogni = $"data:image/gif;base64,{b_tempcogni}";
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
StateHasChanged();
|
||||
}
|
||||
} }
|
82
squirrowse.web/Pages/Galery.razor
Normal file
82
squirrowse.web/Pages/Galery.razor
Normal file
@ -0,0 +1,82 @@
|
||||
@page "/galery"
|
||||
@using LiteDB
|
||||
@using squirrowse.core
|
||||
@using squirrowse.web.Data
|
||||
@inject IJSRuntime jsrun;
|
||||
@inject GaleryService galery;
|
||||
<h3>Galery</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@foreach (var item in _frames.Keys)
|
||||
{
|
||||
<th>
|
||||
<button @onclick="e => _tagsSwitch[item] = !_tagsSwitch.GetValueOrDefault(item)">
|
||||
@(_tagsSwitch[item] ? $" {item}" : $" {item}")
|
||||
</button>
|
||||
</th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in _frames.Keys)
|
||||
{
|
||||
<tr>
|
||||
<div class="demo-gallery card card-default border @(_tagsSwitch[item] ? "collapse" : "")">
|
||||
<ul id="lightgallery" class="list-unstyled row lgalery">
|
||||
|
||||
@foreach (var t in _frames.GetValueOrDefault(item))
|
||||
{
|
||||
<ul class="col-xs-6 col-sm-4 col-md-3 " data-responsive="@t.ImgSrc" data-src="@t.ImgSrc">
|
||||
<a href="./galery">
|
||||
<img class="img-responsive" src="@t.ImgSrc" height="180" width="320"/>
|
||||
|
||||
</a>
|
||||
</ul>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@code {
|
||||
|
||||
private ILiteDatabase repo;
|
||||
private List<string> _tags;
|
||||
private readonly Dictionary<string, bool> _tagsSwitch = new Dictionary<string, bool>();
|
||||
private Dictionary<string, List<Frame>> _frames;
|
||||
private bool Collapsed = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_tags = await galery.tags();
|
||||
foreach (var t in _tags)
|
||||
{
|
||||
_tagsSwitch.Add(t, true);
|
||||
}
|
||||
_frames = await galery.galeryEntireView();
|
||||
|
||||
|
||||
// StateHasChanged();
|
||||
}
|
||||
|
||||
//public async Task Colapse()
|
||||
//{
|
||||
// await jsrun.InvokeVoidAsync("colapseD");
|
||||
//}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await jsrun.InvokeVoidAsync("galeryJs");
|
||||
if (firstRender)
|
||||
{
|
||||
//_frames = null;
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
5
squirrowse.web/Pages/Index.razor
Normal file
5
squirrowse.web/Pages/Index.razor
Normal file
@ -0,0 +1,5 @@
|
||||
@page "/"
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to aws.
|
179
squirrowse.web/Pages/_Host.cshtml
Normal file
179
squirrowse.web/Pages/_Host.cshtml
Normal file
@ -0,0 +1,179 @@
|
||||
@page "/"
|
||||
@namespace squirrowse.web.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="jquery/jquery.js"></script>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>squirrowse.web</title>
|
||||
<base href="~/"/>
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="lib/lightgallery/css/lightgallery.css"/>
|
||||
<link href="css/site.css" rel="stylesheet"/>
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
.demo-gallery > ul { margin-bottom: 0; }
|
||||
|
||||
.demo-gallery > ul > li {
|
||||
float: left;
|
||||
margin-bottom: 15px;
|
||||
margin-right: 20px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a {
|
||||
border: 3px solid #FFF;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mostly-customized-scrollbar::-webkit-scrollbar {
|
||||
background-color: #aaa; /* or add it to the track */
|
||||
height: 8px;
|
||||
overflow: auto;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a > img {
|
||||
-moz-transition: -moz-transform 0.15s ease 0s;
|
||||
-o-transition: -o-transform 0.15s ease 0s;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
-webkit-transition: -webkit-transform 0.15s ease 0s;
|
||||
height: 100%;
|
||||
transform: scale3d(1, 1, 1);
|
||||
transition: transform 0.15s ease 0s;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a:hover > img {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a:hover .demo-gallery-poster > img { opacity: 1; }
|
||||
|
||||
.demo-gallery > ul > li a .demo-gallery-poster {
|
||||
-o-transition: background-color 0.15s ease 0s;
|
||||
-webkit-transition: background-color 0.15s ease 0s;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transition: background-color 0.15s ease 0s;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a .demo-gallery-poster > img {
|
||||
-o-transition: opacity 0.3s ease 0s;
|
||||
-webkit-transition: opacity 0.3s ease 0s;
|
||||
left: 50%;
|
||||
margin-left: -10px;
|
||||
margin-top: -10px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transition: opacity 0.3s ease 0s;
|
||||
}
|
||||
|
||||
.demo-gallery > ul > li a:hover .demo-gallery-poster { background-color: rgba(0, 0, 0, 0.5); }
|
||||
|
||||
.demo-gallery .justified-gallery > a > img {
|
||||
-moz-transition: -moz-transform 0.15s ease 0s;
|
||||
-o-transition: -o-transform 0.15s ease 0s;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
-webkit-transition: -webkit-transform 0.15s ease 0s;
|
||||
height: 100%;
|
||||
transform: scale3d(1, 1, 1);
|
||||
transition: transform 0.15s ease 0s;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.demo-gallery .justified-gallery > a:hover > img {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
|
||||
.demo-gallery .justified-gallery > a:hover .demo-gallery-poster > img { opacity: 1; }
|
||||
|
||||
.demo-gallery .justified-gallery > a .demo-gallery-poster {
|
||||
-o-transition: background-color 0.15s ease 0s;
|
||||
-webkit-transition: background-color 0.15s ease 0s;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transition: background-color 0.15s ease 0s;
|
||||
}
|
||||
|
||||
.demo-gallery .justified-gallery > a .demo-gallery-poster > img {
|
||||
-o-transition: opacity 0.3s ease 0s;
|
||||
-webkit-transition: opacity 0.3s ease 0s;
|
||||
left: 50%;
|
||||
margin-left: -10px;
|
||||
margin-top: -10px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transition: opacity 0.3s ease 0s;
|
||||
}
|
||||
|
||||
.demo-gallery .justified-gallery > a:hover .demo-gallery-poster { background-color: rgba(0, 0, 0, 0.5); }
|
||||
|
||||
.demo-gallery .video .demo-gallery-poster img {
|
||||
height: 48px;
|
||||
margin-left: -24px;
|
||||
margin-top: -24px;
|
||||
opacity: 0.8;
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.demo-gallery.dark > ul > li a { border: 3px solid #04070a; }
|
||||
|
||||
.home .demo-gallery { padding-bottom: 80px; }
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<app>
|
||||
<component type="typeof(App)" render-mode="ServerPrerendered"/>
|
||||
</app>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
<environment include="Staging,Production">
|
||||
An error has occurred. This application may no longer respond until reloaded.
|
||||
</environment>
|
||||
<environment include="Development">
|
||||
An unhandled exception has occurred. See browser dev tools for details.
|
||||
</environment>
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
|
||||
<script src="lib/lightgallery/js/lightgallery-all.js"></script>
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
<script>
|
||||
function galeryJs() {
|
||||
|
||||
$('.lgalery').lightGallery();
|
||||
};
|
||||
|
||||
function colapseD() {
|
||||
$('.collapse').collapse();
|
||||
};
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
19
squirrowse.web/Program.cs
Normal file
19
squirrowse.web/Program.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace squirrowse.web
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||
{
|
||||
return Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>().UseUrls("http://0.0.0.0:5000"); });
|
||||
}
|
||||
}
|
||||
}
|
35
squirrowse.web/Properties/launchSettings.json
Normal file
35
squirrowse.web/Properties/launchSettings.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://192.168.0.13:8000",
|
||||
"sslPort": 443
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"squirrowse.web": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"useSSL": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://192.168.0.13:8000"
|
||||
},
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"publishAllPorts": true,
|
||||
"useSSL": true
|
||||
}
|
||||
}
|
||||
}
|
15
squirrowse.web/Shared/MainLayout.razor
Normal file
15
squirrowse.web/Shared/MainLayout.razor
Normal file
@ -0,0 +1,15 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="sidebar">
|
||||
<NavMenu/>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<div class="top-row px-4">
|
||||
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
|
||||
</div>
|
||||
|
||||
<div class="content px-4">
|
||||
@Body
|
||||
</div>
|
||||
</div>
|
38
squirrowse.web/Shared/NavMenu.razor
Normal file
38
squirrowse.web/Shared/NavMenu.razor
Normal file
@ -0,0 +1,38 @@
|
||||
<div class="top-row pl-4 navbar navbar-dark">
|
||||
<a class="navbar-brand" href="">squirrowse.web</a>
|
||||
<button class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<span class="oi oi-home" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="client">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Client
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="galery">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Galery
|
||||
</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private bool collapseNavMenu = true;
|
||||
|
||||
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
|
||||
|
||||
private void ToggleNavMenu()
|
||||
{
|
||||
collapseNavMenu = !collapseNavMenu;
|
||||
}
|
||||
|
||||
}
|
27
squirrowse.web/Startup.DevExpress.cs
Normal file
27
squirrowse.web/Startup.DevExpress.cs
Normal file
@ -0,0 +1,27 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Generated by the DevExpress.Blazor package.
|
||||
// To prevent this operation, add the DxExtendStartupHost property to the project and set this property to False.
|
||||
//
|
||||
// squirrowse.web.csproj:
|
||||
//
|
||||
// <Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
// <PropertyGroup>
|
||||
// <TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
// <DxExtendStartupHost>False</DxExtendStartupHost>
|
||||
// </PropertyGroup>
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
[assembly: HostingStartup(typeof(squirrowse.web.DevExpressHostingStartup))]
|
||||
|
||||
namespace squirrowse.web {
|
||||
public partial class DevExpressHostingStartup : IHostingStartup {
|
||||
void IHostingStartup.Configure(IWebHostBuilder builder) {
|
||||
builder.ConfigureServices((serviceCollection) => {
|
||||
serviceCollection.AddDevExpressBlazor();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
71
squirrowse.web/Startup.cs
Normal file
71
squirrowse.web/Startup.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using squirrowse.db;
|
||||
using squirrowse.web.Cognitive;
|
||||
using squirrowse.web.Data;
|
||||
|
||||
namespace squirrowse.web
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddRazorPages();
|
||||
services.AddServerSideBlazor().AddHubOptions(x =>
|
||||
{
|
||||
x.EnableDetailedErrors = true;
|
||||
x.MaximumReceiveMessageSize = short.MaxValue;
|
||||
});
|
||||
|
||||
services.AddSingleton<SaveVideo>();
|
||||
services.AddSingleton<Detection>();
|
||||
services.AddSingleton<IAzureCV, AzureCV>();
|
||||
services.AddSingleton<DbContext>();
|
||||
services.AddSingleton<GaleryService>();
|
||||
services.AddSingleton<Bloob>();
|
||||
services.AddSingleton<VideoQ>();
|
||||
services.AddSignalR(x => x.MaximumReceiveMessageSize = ((int)(int.MaxValue / 2))).AddMessagePackProtocol();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UsePathBase(new PathString("/extra"));
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapBlazorHub();
|
||||
endpoints.MapFallbackToPage("/_Host");
|
||||
endpoints.MapHub<ClientHub>("hub");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
39706
squirrowse.web/StaticFiles/haarcascade_frontalface_alt.xml
Normal file
39706
squirrowse.web/StaticFiles/haarcascade_frontalface_alt.xml
Normal file
File diff suppressed because it is too large
Load Diff
22792
squirrowse.web/StaticFiles/haarcascade_lowerbody.xml
Normal file
22792
squirrowse.web/StaticFiles/haarcascade_lowerbody.xml
Normal file
File diff suppressed because it is too large
Load Diff
45530
squirrowse.web/StaticFiles/haarcascade_upperbody.xml
Normal file
45530
squirrowse.web/StaticFiles/haarcascade_upperbody.xml
Normal file
File diff suppressed because it is too large
Load Diff
9
squirrowse.web/_Imports.razor
Normal file
9
squirrowse.web/_Imports.razor
Normal file
@ -0,0 +1,9 @@
|
||||
@using System.Net.Http
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.JSInterop
|
||||
@using squirrowse.web
|
||||
@using squirrowse.web.Shared
|
10
squirrowse.web/appsettings.Development.json
Normal file
10
squirrowse.web/appsettings.Development.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
10
squirrowse.web/appsettings.json
Normal file
10
squirrowse.web/appsettings.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
BIN
squirrowse.web/db-log.db
Normal file
BIN
squirrowse.web/db-log.db
Normal file
Binary file not shown.
BIN
squirrowse.web/db.db
Normal file
BIN
squirrowse.web/db.db
Normal file
Binary file not shown.
14
squirrowse.web/libman.json
Normal file
14
squirrowse.web/libman.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"defaultProvider": "cdnjs",
|
||||
"libraries": [
|
||||
{
|
||||
"library": "lightgallery@1.6.12",
|
||||
"destination": "wwwroot/lib/lightgallery/"
|
||||
},
|
||||
{
|
||||
"library": "jquery@3.4.1",
|
||||
"destination": "wwwroot/jquery/"
|
||||
}
|
||||
]
|
||||
}
|
44
squirrowse.web/squirrowse.web.csproj
Normal file
44
squirrowse.web/squirrowse.web.csproj
Normal file
@ -0,0 +1,44 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<UserSecretsId>e06d99cb-4df6-41f0-8639-cd34df940830</UserSecretsId>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CNTK.Deps.OpenCV.Zip" Version="2.8.0-rc0.dev20200201" />
|
||||
<PackageReference Include="DevExpress.Blazor" Version="19.2.4-preview" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.5" />
|
||||
<PackageReference Include="Microsoft.Azure.CognitiveServices.Vision.ComputerVision" Version="6.0.0-dev.20190919.3" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.10" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.2.0.20200208" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.ubuntu.18.04-x64" Version="4.2.0.20200208" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\squirrowse.core\squirrowse.core.csproj" />
|
||||
<ProjectReference Include="..\squirrowse.db\squirrowse.db.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="StaticFiles\haarcascade_frontalface_alt.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StaticFiles\haarcascade_lowerbody.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StaticFiles\haarcascade_upperbody.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties appsettings_1development_1json__JsonSchema="http://json.schemastore.org/asmdef" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
|
||||
</Project>
|
7
squirrowse.web/wwwroot/css/bootstrap/bootstrap.min.css
vendored
Normal file
7
squirrowse.web/wwwroot/css/bootstrap/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
86
squirrowse.web/wwwroot/css/open-iconic/FONT-LICENSE
Normal file
86
squirrowse.web/wwwroot/css/open-iconic/FONT-LICENSE
Normal file
@ -0,0 +1,86 @@
|
||||
SIL OPEN FONT LICENSE Version 1.1
|
||||
|
||||
Copyright (c) 2014 Waybury
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
21
squirrowse.web/wwwroot/css/open-iconic/ICON-LICENSE
Normal file
21
squirrowse.web/wwwroot/css/open-iconic/ICON-LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Waybury
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
114
squirrowse.web/wwwroot/css/open-iconic/README.md
Normal file
114
squirrowse.web/wwwroot/css/open-iconic/README.md
Normal file
@ -0,0 +1,114 @@
|
||||
[Open Iconic v1.1.1](http://useiconic.com/open)
|
||||
===========
|
||||
|
||||
### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons)
|
||||
|
||||
|
||||
|
||||
## What's in Open Iconic?
|
||||
|
||||
* 223 icons designed to be legible down to 8 pixels
|
||||
* Super-light SVG files - 61.8 for the entire set
|
||||
* SVG sprite—the modern replacement for icon fonts
|
||||
* Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats
|
||||
* Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats
|
||||
* PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
#### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections.
|
||||
|
||||
### General Usage
|
||||
|
||||
#### Using Open Iconic's SVGs
|
||||
|
||||
We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute).
|
||||
|
||||
```
|
||||
<img src="/open-iconic/svg/icon-name.svg" alt="icon name">
|
||||
```
|
||||
|
||||
#### Using Open Iconic's SVG Sprite
|
||||
|
||||
Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack.
|
||||
|
||||
Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `<svg>` *tag and a unique class name for each different icon in the* `<use>` *tag.*
|
||||
|
||||
```
|
||||
<svg class="icon">
|
||||
<use xlink:href="open-iconic.svg#account-login" class="icon-account-login"></use>
|
||||
</svg>
|
||||
```
|
||||
|
||||
Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `<svg>` tag with equal width and height dimensions.
|
||||
|
||||
```
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
```
|
||||
|
||||
Coloring icons is even easier. All you need to do is set the `fill` rule on the `<use>` tag.
|
||||
|
||||
```
|
||||
.icon-account-login {
|
||||
fill: #f00;
|
||||
}
|
||||
```
|
||||
|
||||
To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/).
|
||||
|
||||
#### Using Open Iconic's Icon Font...
|
||||
|
||||
|
||||
##### …with Bootstrap
|
||||
|
||||
You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}`
|
||||
|
||||
|
||||
```
|
||||
<link href="/open-iconic/font/css/open-iconic-bootstrap.css" rel="stylesheet">
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
<span class="oi oi-icon-name" title="icon name" aria-hidden="true"></span>
|
||||
```
|
||||
|
||||
##### …with Foundation
|
||||
|
||||
You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}`
|
||||
|
||||
```
|
||||
<link href="/open-iconic/font/css/open-iconic-foundation.css" rel="stylesheet">
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
<span class="fi-icon-name" title="icon name" aria-hidden="true"></span>
|
||||
```
|
||||
|
||||
##### …on its own
|
||||
|
||||
You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}`
|
||||
|
||||
```
|
||||
<link href="/open-iconic/font/css/open-iconic.css" rel="stylesheet">
|
||||
```
|
||||
|
||||
```
|
||||
<span class="oi" data-glyph="icon-name" title="icon name" aria-hidden="true"></span>
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
### Icons
|
||||
|
||||
All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT).
|
||||
|
||||
### Fonts
|
||||
|
||||
All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web).
|
1
squirrowse.web/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css
vendored
Normal file
1
squirrowse.web/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user