Webcam for WPF .NET Core 3.1 - wpf

I've tried a lot of dependencies in my project for webcam, including :
OpenCVSharp
WpfWebcamControl
WebcamCapturer.Core
But seems like all of those dependencies does not fully compatible with my project.
My current project dependencies :
Microsoft.NETCore.App v3.1
Microsoft.WindowsDesktop.App.WPF
Is there any compatible webcam dependency for WPF .NET Core v3.1 ?

These packages are incompatible with .NET Core 3.1.
WpfWebcamControl (>= .NET Framework 4.6)
WebcamCapturer.Core (>= .NET Framework 4.7.2)
For OpenCV, you might be using the wrong package, as it is indeed compatible with .NET Core 3.1.
OpenCVSharp (.NET Framework)
OpenCVSharp4 (>= .NET Framework 4.6.2, >= .NET Standard 2.0, >= .NET Core 2.1)
For more info and packages, see GitHub and a short tutorial here.
Please note that the OpenCVSharp4 package is the core package, depending on your use-case, you might instead use OpenCvSharp4.Windows and optionally OpenCvSharp4.WpfExtensions. Please refer to the project page GitHub and the Wiki for more information.

A bit of sharing how I done it based on the accepted answer by #thatguy
first, Installing OpenCvSharp4.Windows and OpenCvSharp4.WpfExtensions into your wpf .NET Core application.
Then I put <Image x:Name="image1" Width="400" Height="300" /> in my xaml file
and use WriteableBitmapConverter.ToWriteableBitmap to keep updating my image
bellow is my code behind
public partial class MainWindow : System.Windows.Window
{
private System.Timers.Timer MyDataTimer;
FrameSource frameSource = Cv2.CreateFrameSource_Camera(0);
public MainWindow()
{
InitializeComponent();
MyDataTimer = new System.Timers.Timer();
MyDataTimer.Elapsed += new ElapsedEventHandler(MyDataTimer_Elapsed);
MyDataTimer.Enabled = true;
MyDataTimer.Interval = 1 * 1;
MyDataTimer.Start();
}
private void MyDataTimer_Elapsed(object source, ElapsedEventArgs e)
{
try
{
MyDataTimer.Stop();
MyDataTimer.Interval = 1 * 1;
this.Dispatcher.Invoke(new Action(LoadImages));
MyDataTimer.Start();
}
catch (Exception ex)
{
}
finally
{
MyDataTimer.Start();
}
}
private void LoadImages()
{
using (var mat = new Mat())
{
frameSource.NextFrame(mat);
var wb = WriteableBitmapConverter.ToWriteableBitmap(mat);
image1.Source = null;
image1.Source = wb;
}
}
}
Hope this would help!

Related

Cefsharp Winform shows images blurred

Tools used : .net framework 4.7.2, Windows 7 x64, Visual Studio 2019
I'm creating a Cefsharp Winform browser.
It works as an simple GUI for my asp.net core app.
The problem stands on the fact that the pictures are very blurred.
If i use firefox/chrome the pictures are high quality and clean.
My Form1.cs :
public ChromiumWebBrowser browser;
public void InitBrowser()
{
CefSharpSettings.WcfEnabled = true;
var settings = new CefSettings();
//Absolute path to your applications executable
settings.BrowserSubprocessPath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
Cef.EnableHighDPISupport();
Cef.RefreshWebPlugins();
Cef.Initialize(new CefSettings());
browser = new ChromiumWebBrowser("https://localhost:5001")
{
MenuHandler = new CustomMenuHandler()
};
this.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
}
public Form1()
{
InitializeComponent();
InitBrowser();
}
the debug_.log :
[0529/224714.592:ERROR:gpu_init.cc(426)] Passthrough is not supported, GL is disabled
[0529/225010.059:WARNING:dns_config_service_win.cc(712)] Failed to read DnsConfig.
What's wrong with this code?

AssemblyLoadContext.Unload does not unload a Wpf Library

I am writing here the same issue posted on Github since I don't see much traffic there recently.
.NET Core Version: 3.1.9 and .Net 5
Windows version: 10.0.18363
Does the bug reproduce also in WPF for .NET Framework 4.8?: AssemblyLoadContext not supported
I am trying to load and unload on demand a Wpf App library (and all the related dependencies). Everything works, but none of the assemblies get unloaded when calling the Unload method.
If I replace the Wpf library with a .Net Core library containing a few sample methods, I can see the library removed from VS Modules window after a couple of GC iterations.
If I'm not wrong I should expect AssemblyLoadContext to load WpfLibrary and related dependencies (PresentationCore, PresentationFramework etc), but WpfLibrary is the only one loaded. All the other dependencies seems be loaded in the default context. May be that I misunderstood how it works, but to me seems that the framework dependencies prevent the unloading.
Also I am not sure if the problem I am reporting is related to this and/or this.
I attached a sample project which is structured like this:
Project 1 (MainApp, a console project with added System.Windows.Forms reference to enable message pump)
class Program
{
class WpfAppAssemblyLoadContext : AssemblyLoadContext
{
public WpfAppAssemblyLoadContext() : base(true) { }
protected override Assembly Load(AssemblyName assemblyName) => null;
}
[MethodImpl(MethodImplOptions.NoInlining),]
public static void TestRun()
{
var context = new WpfAppAssemblyLoadContext();
var assembly = context.LoadFromAssemblyPath($"{Environment.CurrentDirectory}\\WpfLibrary.dll");
var inst = (IProxy) assembly.CreateInstance("WpfLibrary.MainWindow");
inst.ShowWindow();
inst.CloseWindow();
context.Unload();
assembly = null;
context = null;
inst = null;
}
[STAThread,]
static void Main(string[] args)
{
TestRun();
for (var i = 0; i < 100; i++) {
GC.Collect();
GC.WaitForPendingFinalizers();
}
Application.Run();
}
}
Project 2 (ProxyInterface)
namespace ProxyInterface
{
public interface IProxy
{
void ShowWindow();
void CloseWindow();
}
}
Project 3 (a regular wpf library with implementation of interface in Project 2 )
namespace WpfLibrary
{
public partial class MainWindow : Window, IProxy
{
public MainWindow()
{
InitializeComponent();
}
public void ShowWindow() { Show();}
public void CloseWindow() { Close();}
}
}
UnloadWpfLibrary.zip
(Solution file inside "MainApp" folder)
Further updates:
DotNet team added the issue to "Future Milestone", therefore I have to deduce that they recognized this as a bug. I have no idea on when we will see Wpf working with AssemblyLoadContext.
Seems to be that there is a workaround which involve splitting the target assembly into two separate assemblies. I attached the project with the suggested modifications and this time one of the two assemblies is unloaded, but all of the others are still loaded included WpfLibrary.
UnloadWpfLibraryWithWorkaround.zip
I think that for me it's time to give up and recur to IPC (named pipes) although I am not sure if this could be a valid replacement.
May be I missed something and someone more expert can do further progress and attach here the project with the correct modifications, it would be of great benefit for all the users that want to use ALC to load and unload WPF.
It would be a total of 4 projects just to load and unload a wpf assembly on demand and this is not exactly clean, but if the final result is the same it would be acceptable.

Cannot find all types required by the async modifier

I get the following two compiler errors (Resharper 7.0.1 reports no errors):
Predefined type 'System.Runtime.CompilerServices.IAsyncStateMachine' is not defined or imported
Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?
but this code will not compile:
public class Class1
{
public Class1()
{
Um();
}
public async Task<DownloadStringCompletedEventArgs> Um()
{
var client = new WebClient();
return await Observable.FromEvent<DownloadStringCompletedEventHandler, DownloadStringCompletedEventArgs>(x => client.DownloadStringCompleted += x,
x => client.DownloadStringCompleted -= x);
}
}
I've seen MSBuild doesn't find async required references already except that I have VS 2012 NOT VS 11 Beta - although it was installed. Also I tried it in a brand new assembly, no xaml namespace pointing to the application.
You need the Async Targeting Pack to support async in Silverlight 5.
We just released a beta of Async for .NET Framework 4, Silverlight 4 and 5, and Windows Phone 7.5: http://blogs.msdn.com/b/bclteam/archive/2012/10/22/using-async-await-without-net-framework-4-5.aspx.
You cannot use AsyncCTP in Visual Studio 2012. You can use Async Targeting Pack (available on NuGet) for Silverlight 5. No solution is yet available for Silverlight 4, not sure if there will be any.

passing values between silverlight applications

I have created a Silverlight Business Application which runs as my main silverlight page. For each hyperlink button on my "menu" I launch another Silverlight Application which is created as a different project in Visual Studio. These are non-Business Applications.
Everything is working well. However I'm trying to pass a value from my main SL application to the SL application inside.
I have been googling a lot and cannot find an answer.
As I understand the InitParam is used between ASP and SL, and not between SL apps.
Since the App config is launched for the first SL app and the app config for the second application in never lauched, I'm not able to use that (thats at least my understanding)
The value I want to pass is the login name and role, which is possible to get from webcontext in the Silverlight Business application, but I'm unable to get webcontext in the non-Business application which run inside.
This is how I launch my SL app inside the main SL app:
public Customers()
{
InitializeComponent();
this.Title = ApplicationStrings.CustomersPageTitle;
if (WebContext.Current.User.IsInRole("Users") || WebContext.Current.User.IsInRole("Administrators"))
{
WebClient client = new WebClient();
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(new Uri("customers.xap", UriKind.Relative));
}
}
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
string appManifest = new StreamReader(Application.GetResourceStream(new StreamResourceInfo(e.Result, null),
new Uri("AppManifest.xaml", UriKind.Relative)).Stream).ReadToEnd();
XElement deploymentRoot = XDocument.Parse(appManifest).Root;
List<XElement> deploymentParts =
(from assemblyParts in deploymentRoot.Elements().Elements() select assemblyParts).ToList();
Assembly asm = null;
AssemblyPart asmPart = new AssemblyPart();
foreach (XElement xElement in deploymentParts)
{
string source = xElement.Attribute("Source").Value;
StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(e.Result, "application/binary"), new Uri(source, UriKind.Relative));
if (source == "customers.dll")
{
asm = asmPart.Load(streamInfo.Stream);
}
else
{
asmPart.Load(streamInfo.Stream);
}
}
UIElement myData = asm.CreateInstance("customers.MainPage") as UIElement;
stackCustomers.Children.Add(myData);
stackCustomers.UpdateLayout();
}
Anyone?
i agree with ChrisF ,I think that Prism or MEF can resolve you problem.
any way,do some search on the web and look for these two classes:
**
LocalMessageSender
LocalMessageReceiver
**
good luck

silverlight 4, dynamically loading xap modules

I know that it is possible to load xap modules dynamically using Prism or MEF framework. However, I'd like not to use those frameworks; instead load my xap files manually. So, I created the following class (adapted from internet):
public class XapLoader
{
public event XapLoadedEventHandler Completed;
private string _xapName;
public XapLoader(string xapName)
{
if (string.IsNullOrWhiteSpace(xapName))
throw new ArgumentException("Invalid module name!");
else
_xapName = xapName;
}
public void Begin()
{
Uri uri = new Uri(_xapName, UriKind.Relative);
if (uri != null)
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += onXapLoadingResponse;
wc.OpenReadAsync(uri);
}
}
private void onXapLoadingResponse(object sender, OpenReadCompletedEventArgs e)
{
if ((e.Error == null) && (e.Cancelled == false))
initXap(e.Result);
if (Completed != null)
{
XapLoadedEventArgs args = new XapLoadedEventArgs();
args.Error = e.Error;
args.Cancelled = e.Cancelled;
Completed(this, args);
}
}
private void initXap(Stream stream)
{
string appManifest = new StreamReader(Application.GetResourceStream(
new StreamResourceInfo(stream, null), new Uri("AppManifest.xaml",
UriKind.Relative)).Stream).ReadToEnd();
XElement deploy = XDocument.Parse(appManifest).Root;
List<XElement> parts = (from assemblyParts in deploy.Elements().Elements()
select assemblyParts).ToList();
foreach (XElement xe in parts)
{
string source = xe.Attribute("Source").Value;
AssemblyPart asmPart = new AssemblyPart();
StreamResourceInfo streamInfo = Application.GetResourceStream(
new StreamResourceInfo(stream, "application/binary"),
new Uri(source, UriKind.Relative));
asmPart.Load(streamInfo.Stream);
}
}
}
public delegate void XapLoadedEventHandler(object sender, XapLoadedEventArgs e);
public class XapLoadedEventArgs : EventArgs
{
public Exception Error { get; set; }
public bool Cancelled { get; set; }
}
The above code works fine; I can load any xap the following way:
XapLoader xapLoader = new XapLoader("Sales.xap");
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed);
xapLoader.Begin();
Now, I have a UserControl called InvoiceView in the Sales.xap project, so I would like to instantiate the class. In the current project (Main.xap) I added reference to Sales.xap project, however, since I load it manually I set "Copy Local = False". But when executed, the following code throws TypeLoadException:
Sales.InvoiceView view = new Sales.InvoiceView();
It seems the code can't find InvoiceView class. But I checked that XapLoader's initXap() method was successfully executed. So why the code can't find InvoiceView class? Can someone help me with this problem?
This is based on the asker's self-answer below, rather than the question.
If you delete a project/module the output DLLs/XAP files do hang around. If you click the "show all files" button you will see some these left-over output files in your clientbin, bin and obj folders of related projects.
You can delete them individually from the project, or, when in doubt, search for all BIN and OBJ (e.g. using desktop explorer) and delete all those folders. The BIN/CLIENTBIN/OBJ folders will be recreated when needed (this the job that the "clean" option in Visual Studio should have done!)
Hope this helps.
Ok, I found the cause. The above code works. After creating a new silverlight project (Sales.xap) I happened to compile my solution once. Then I deleted App class in the Sales.xap and renamed default MainPage class to SalesView. However, no matter how many times I compile my solution, Visual Studio's development web server was loading the first version of Sales.xap (where from?), so my code couldn't find SalesView. In my host Asp.Net project I set development server's port to a different port number, and the problem gone. So the problem was with Visual Studio's development server. Apparently it is keeping compiled xap files in some temporary folder, and doesn't always update those xap files when source code changed.
What I do to avoid such problems when executing freshly compiled Silverlight is clear the browser cache, chrome even has a clear silverlight cache ;)
this XAP Cache phenomena is often due to the visual studio embedded web server (ASP.NET Development Server).
Just stop the occurence of this server and the cache will be cleared.
Start again your project and the latest build of your xap is called.

Resources