英文:
Cannot Add Tuple to BlockingCollection: Error CS1503 in C#
问题
I'm working on a project that involves object detection with real-time video in C#. As part of the project, I use a BlockingCollection to manage a list of bounding boxes for detected objects, and the details for each bounding box are held in a tuple. However, I'm encountering an error CS1503 when trying to add new tuples to the collection. Here's how I defined the BlockingCollection:
BlockingCollection<Tuple<int, int, int, int, string, string, Scalar, DateTime>> ObjectDetectionBbox = new BlockingCollection<Tuple<int, int, int, int, string, string, Scalar, DateTime>>();
And here's the line where I'm trying to add a new tuple to the collection:
ObjectDetectionBbox.Add(Tuple.Create(
topLeft.X,
topLeft.Y,
bottomRight.X - topLeft.X,
bottomRight.Y - topLeft.Y,
className,
trackedName,
classColor,
bboxTimestamp
));
The error message is:
Error CS1503 Argument 1: cannot convert from 'System.Tuple<int, int, int, int, string, string, OpenCvSharp.Scalar, System.Tuple<System.DateTime>>' to 'System.Tuple<int, int, int, int, string, string, OpenCvSharp.Scalar, System.DateTime>'
The error message seems to suggest that my tuple has a Tuple
I've confirmed that bboxTimestamp is indeed a DateTime, and I'm not sure why this error is happening.
英文:
I'm working on a project that involves object detection with real-time video in C#. As part of the project, I use a BlockingCollection to manage a list of bounding boxes for detected objects, and the details for each bounding box are held in a tuple. However, I'm encountering an error CS1503 when trying to add new tuples to the collection. Here's how I defined the BlockingCollection:
BlockingCollection<Tuple<int, int, int, int, string, string, Scalar, DateTime>> ObjectDetectionBbox = new BlockingCollection<Tuple<int, int, int, int, string, string, Scalar, DateTime>>();
And here's the line where I'm trying to add a new tuple to the collection:
ObjectDetectionBbox.Add(Tuple.Create(
topLeft.X,
topLeft.Y,
bottomRight.X - topLeft.X,
bottomRight.Y - topLeft.Y,
className,
trackedName,
classColor,
bboxTimestamp
));
The error message is:
> Error CS1503 Argument 1: cannot convert from 'System.Tuple<int, int, int, int, string, string, OpenCvSharp.Scalar, System.Tuple<System.DateTime>>' to 'System.Tuple<int, int, int, int, string, string, OpenCvSharp.Scalar, System.DateTime>'
The error message seems to suggest that my tuple has a Tuple<DateTime> as the last element, but as you can see in my code, the last element is a DateTime.
I've confirmed that bboxTimestamp is indeed a DateTime, and I'm not sure why this error is happening.
Does anyone know why this might be happening and how I could fix it? Any help would be greatly appreciated.
HERE IS THE FULL CODE FOR REFERENCE:
public async Task Main(System.Windows.Controls.Image imageControl, CancellationToken token)
{
BlockingCollection<Tuple<int, int, int, int, string, string, Scalar, DateTime>> ObjectDetectionBbox = new BlockingCollection<Tuple<int, int, int, int, string, string, Scalar, DateTime>>();
BlockingCollection<Tuple<Mat, DateTime>> frameBuffer = new BlockingCollection<Tuple<Mat, DateTime>>(); // Our new frame buffer
string cameraUrl = "http://cam1.infolink.ru/mjpg/video.mjpg";
//string cameraUrl = "http://hotel-seerose.dyndns.org:8001/cgi-bin/faststream.jpg?stream=full&fps=0";
string URLreturnBbox = "http://localhost:8003/api/v1/camera/get_frame"; // Updated endpoint URL
await initializeRunServer(cameraUrl);
var idFaceDictionary = new ConcurrentDictionary<long, object>();
var classNames = await GetClassNames();
var colorList = InitColorList(classNames.Count);
Task processFrameTask = Task.Run(() => ProcessTask(imageControl, token, URLreturnBbox, classNames, colorList,idFaceDictionary, ObjectDetectionBbox));
// Create video source
MJPEGStream stream = new MJPEGStream(cameraUrl);
// New frame event handler
stream.NewFrame += (sender, eventArgs) =>
{
// Convert AForge.NET's Bitmap to OpenCvSharp's Mat
Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone();
Mat frame = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);
// Get bbox info from ObjectDetectionBbox, if any
while (ObjectDetectionBbox.TryTake(out var bbox)) // Replace if with while to draw all available bounding boxes
{
// Ensure we only proceed if there is a detection and a valid class name.
if (!string.IsNullOrEmpty(bbox.Item5))
{
if (bbox.Item5 == "person" && bbox.Item6 != null) // Display if person is detected
{
DrawPerson(
frame,
bbox.Item1,
bbox.Item2,
bbox.Item3,
bbox.Item4,
bbox.Item6,
bbox.Item7
);
}
else
{
Cv2.Rectangle(frame, new OpenCvSharp.Point(bbox.Item1, bbox.Item2), new OpenCvSharp.Point(bbox.Item1 + bbox.Item3, bbox.Item2 + bbox.Item4), bbox.Item7, 1);
var caption = bbox.Item5;
Cv2.PutText(frame, caption, new OpenCvSharp.Point(bbox.Item1, bbox.Item2), HersheyFonts.HersheyComplex, 1, bbox.Item7, 1);
}
}
}
// Process and display the frame
Application.Current.Dispatcher.Invoke(() =>
{
UpdateDisplay(frame, imageControl);
});
};
// Start video capture
stream.Start();
// Wait until cancellation is requested
while (!token.IsCancellationRequested)
{
await Task.Delay(20);
}
// Stop video capture
stream.SignalToStop();
stream.WaitForStop();
}
public async Task ProcessTask(System.Windows.Controls.Image imageControl, CancellationToken token, string URLreturnBbox, IDictionary<int, string> classNames, List<Scalar> colorList, ConcurrentDictionary<long, object> idFaceDictionary, BlockingCollection<Tuple<int, int, int, int, string, string, Scalar, DateTime>> ObjectDetectionBbox)
{
while (!token.IsCancellationRequested)
{
if (RunOTModel && ObjectTracking)
{
await GetObjectDetectionBbox(URLreturnBbox, classNames, colorList, idFaceDictionary, ObjectDetectionBbox);
}
}
}
private async Task GetObjectDetectionBbox(string boundingBoxesUrl, IDictionary<int, string> classNames, List<Scalar> colorList, ConcurrentDictionary<long, object> idFaceDictionary, BlockingCollection<Tuple<int, int, int, int, string, string, Scalar, DateTime>> ObjectDetectionBbox)
{
var resultsList = await RunYolo(boundingBoxesUrl);
// New dictionary to keep track of names already assigned
var assignedNames = new ConcurrentDictionary<string, object>();
foreach (var results in resultsList)
{
if (!results.ContainsKey("class_")) continue;
var classIndex = int.Parse(results["class_"].ToString());
var className = classNames[classIndex];
var classColor = colorList[classIndex];
var topLeft = new OpenCvSharp.Point((long)results["x"], (long)results["y"]);
var bottomRight = new OpenCvSharp.Point((long)results["w"], (long)results["h"]);
string trackedName = null;
long trackId = 0; // initialize with default value
bool hasTrackId = results.ContainsKey("track_id");
DateTime bboxTimestamp = DateTime.Parse(results["timestamp"].ToString());
if (hasTrackId)
{
trackId = (long)results["track_id"];
}
if (OTFaceRecognition && hasTrackId && className == "person" && !idFaceDictionary.ContainsKey(trackId))
{
if (results.ContainsKey("result") && results["result"] != null)
{
var resultStr = results["result"].ToString();
// Check if this name has not been assigned already
if (!string.IsNullOrEmpty(resultStr) && !assignedNames.ContainsKey(resultStr))
{
// Remove any existing entries with the same value
foreach (var kvp in idFaceDictionary.Where(kvp => kvp.Value.Equals(resultStr)).ToList())
{
idFaceDictionary.TryRemove(kvp.Key, out _);
}
// Add the new entry
idFaceDictionary.TryAdd(trackId, resultStr);
// Add this name to the assigned names
assignedNames[resultStr] = new object();
}
}
}
if (OTFaceRecognition && hasTrackId)
{
trackedName = idFaceDictionary.ContainsKey(trackId)
? $"{idFaceDictionary[trackId]} - ID {results["track_id"]}"
: null;
}
ObjectDetectionBbox.Add(Tuple.Create(
topLeft.X, // int
topLeft.Y, // int
bottomRight.X - topLeft.X, // int
bottomRight.Y - topLeft.Y, // int
className, // string
trackedName, // string
classColor, // Scalar
bboxTimestamp // DateTime
));
}
}
答案1
得分: 3
Tuple.Create<T1,T2,T3,T4,T5,T6,T7,T8>(T1, T2, T3, T4, T5, T6, T7, T8)
的返回类型如下:
Tuple<T1,T2,T3,T4,T5,T6,T7,Tuple<T8>>
所以最后一个元素不是类型,而是单一元组,因此会出现错误。最小可重现示例如下:
Tuple<int, int, int, int, string, string, double, DateTime> tup
= Tuple.Create(1, 1, 1, 1, "", "", 2.0, DateTime.UtcNow);
您可以直接使用 Tuple
的构造函数:
Tuple<int, int, int, int, string, string, double, DateTime> tup
= new Tuple<int, int, int, int, string, string, double, DateTime>(1, 1, 1, 1, "", "", 2.0, DateTime.UtcNow);
但一般来说,我建议避免使用元组来表示这样数量多的项 - 最好引入一个类/结构体/记录。
英文:
Tuple.Create<T1,T2,T3,T4,T5,T6,T7,T8>(T1, T2, T3, T4, T5, T6, T7, T8)
has the following return type:
Tuple<T1,T2,T3,T4,T5,T6,T7,Tuple<T8>>
So the last element is not the the type but tuple of single hence the error. Minimal reproducible example would be something like the following:
Tuple<int, int, int, int, string, string, double, DateTime> tup
= Tuple.Create(1, 1, 1, 1, "", "", 2.0, DateTime.UtcNow);
You can use the ctor for Tuple
directly:
Tuple<int, int, int, int, string, string, double, DateTime> tup
= new Tuple<int, int, int, int, string, string, double, DateTime>(1, 1, 1, 1, "", "", 2.0, DateTime.UtcNow);
But in general I would recommend to avoid using tuples for such "big" number of items - just introduce a class/struct/record.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论