[cscore] Add UYVY image support (#4700)

This commit is contained in:
Peter Johnson
2022-11-23 22:00:31 -08:00
committed by GitHub
parent 4307d0ee8b
commit 2bca43779e
11 changed files with 77 additions and 6 deletions

View File

@@ -13,7 +13,8 @@ public class VideoMode {
kYUYV(2),
kRGB565(3),
kBGR(4),
kGray(5);
kGray(5),
kUYVY(6);
private final int value;

View File

@@ -217,7 +217,7 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
// Color convert
switch (pixelFormat) {
case VideoMode::kRGB565:
// If source is YUYV or Gray, need to convert to BGR first
// If source is YUYV, UYVY, or Gray, need to convert to BGR first
if (cur->pixelFormat == VideoMode::kYUYV) {
// Check to see if BGR version already exists...
if (Image* newImage =
@@ -226,6 +226,14 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
} else {
cur = ConvertYUYVToBGR(cur);
}
} else if (cur->pixelFormat == VideoMode::kUYVY) {
// Check to see if BGR version already exists...
if (Image* newImage =
GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
} else {
cur = ConvertUYVYToBGR(cur);
}
} else if (cur->pixelFormat == VideoMode::kGray) {
// Check to see if BGR version already exists...
if (Image* newImage =
@@ -237,7 +245,7 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
}
return ConvertBGRToRGB565(cur);
case VideoMode::kGray:
// If source is YUYV or RGB565, need to convert to BGR first
// If source is YUYV, UYVY, or RGB565, need to convert to BGR first
if (cur->pixelFormat == VideoMode::kYUYV) {
// Check to see if BGR version already exists...
if (Image* newImage =
@@ -246,6 +254,14 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
} else {
cur = ConvertYUYVToBGR(cur);
}
} else if (cur->pixelFormat == VideoMode::kUYVY) {
// Check to see if BGR version already exists...
if (Image* newImage =
GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
} else {
cur = ConvertUYVYToBGR(cur);
}
} else if (cur->pixelFormat == VideoMode::kRGB565) {
// Check to see if BGR version already exists...
if (Image* newImage =
@@ -260,6 +276,8 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
case VideoMode::kMJPEG:
if (cur->pixelFormat == VideoMode::kYUYV) {
cur = ConvertYUYVToBGR(cur);
} else if (cur->pixelFormat == VideoMode::kUYVY) {
cur = ConvertUYVYToBGR(cur);
} else if (cur->pixelFormat == VideoMode::kRGB565) {
cur = ConvertRGB565ToBGR(cur);
} else if (cur->pixelFormat == VideoMode::kGray) {
@@ -271,6 +289,7 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
}
break;
case VideoMode::kYUYV:
case VideoMode::kUYVY:
default:
return nullptr; // Unsupported
}
@@ -351,6 +370,28 @@ Image* Frame::ConvertYUYVToBGR(Image* image) {
return rv;
}
Image* Frame::ConvertUYVYToBGR(Image* image) {
if (!image || image->pixelFormat != VideoMode::kUYVY) {
return nullptr;
}
// Allocate a BGR image
auto newImage =
m_impl->source.AllocImage(VideoMode::kBGR, image->width, image->height,
image->width * image->height * 3);
// Convert
cv::cvtColor(image->AsMat(), newImage->AsMat(), cv::COLOR_YUV2BGR_UYVY);
// Save the result
Image* rv = newImage.release();
if (m_impl) {
std::scoped_lock lock(m_impl->mutex);
m_impl->images.push_back(rv);
}
return rv;
}
Image* Frame::ConvertBGRToRGB565(Image* image) {
if (!image || image->pixelFormat != VideoMode::kBGR) {
return nullptr;

View File

@@ -195,6 +195,7 @@ class Frame {
Image* ConvertMJPEGToBGR(Image* image);
Image* ConvertMJPEGToGray(Image* image);
Image* ConvertYUYVToBGR(Image* image);
Image* ConvertUYVYToBGR(Image* image);
Image* ConvertBGRToRGB565(Image* image);
Image* ConvertRGB565ToBGR(Image* image);
Image* ConvertBGRToGray(Image* image);

View File

@@ -74,6 +74,7 @@ class Image {
switch (pixelFormat) {
case VideoMode::kYUYV:
case VideoMode::kRGB565:
case VideoMode::kUYVY:
type = CV_8UC2;
break;
case VideoMode::kBGR:

View File

@@ -460,6 +460,9 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
case VideoMode::kGray:
os << "gray";
break;
case VideoMode::kUYVY:
os << "UYVY";
break;
default:
os << "unknown";
break;
@@ -569,6 +572,9 @@ void MjpegServerImpl::ConnThread::SendJSON(wpi::raw_ostream& os,
case VideoMode::kGray:
os << "gray";
break;
case VideoMode::kUYVY:
os << "UYVY";
break;
default:
os << "unknown";
break;
@@ -740,8 +746,9 @@ void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
// for adding it if required.
addDHT = JpegNeedsDHT(data, &size, &locSOF);
break;
case VideoMode::kYUYV:
case VideoMode::kUYVY:
case VideoMode::kRGB565:
case VideoMode::kYUYV:
default:
// Bad frame; sleep for 10 ms so we don't consume all processor time.
std::this_thread::sleep_for(std::chrono::milliseconds(10));

View File

@@ -26,6 +26,7 @@ void RawSourceImpl::PutFrame(const CS_RawFrame& image) {
switch (image.pixelFormat) {
case VideoMode::kYUYV:
case VideoMode::kRGB565:
case VideoMode::kUYVY:
type = CV_8UC2;
break;
case VideoMode::kBGR:

View File

@@ -198,6 +198,8 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
mode.pixelFormat = cs::VideoMode::kBGR;
} else if (wpi::equals_lower(str, "gray")) {
mode.pixelFormat = cs::VideoMode::kGray;
} else if (wpi::equals_lower(str, "uyvy")) {
mode.pixelFormat = cs::VideoMode::kUYVY;
} else {
SWARNING("SetConfigJson: could not understand pixel format value '{}'",
str);
@@ -360,6 +362,9 @@ wpi::json SourceImpl::GetConfigJsonObject(CS_Status* status) {
case VideoMode::kGray:
pixelFormat = "gray";
break;
case VideoMode::kUYVY:
pixelFormat = "uyvy";
break;
default:
break;
}

View File

@@ -93,7 +93,8 @@ enum CS_PixelFormat {
CS_PIXFMT_YUYV,
CS_PIXFMT_RGB565,
CS_PIXFMT_BGR,
CS_PIXFMT_GRAY
CS_PIXFMT_GRAY,
CS_PIXFMT_UYVY
};
/**

View File

@@ -68,7 +68,8 @@ struct VideoMode : public CS_VideoMode {
kYUYV = CS_PIXFMT_YUYV,
kRGB565 = CS_PIXFMT_RGB565,
kBGR = CS_PIXFMT_BGR,
kGray = CS_PIXFMT_GRAY
kGray = CS_PIXFMT_GRAY,
kUYVY = CS_PIXFMT_UYVY
};
VideoMode() {
pixelFormat = 0;

View File

@@ -82,6 +82,8 @@ static VideoMode::PixelFormat ToPixelFormat(__u32 pixelFormat) {
return VideoMode::kBGR;
case V4L2_PIX_FMT_GREY:
return VideoMode::kGray;
case V4L2_PIX_FMT_UYVY:
return VideoMode::kUYVY;
default:
return VideoMode::kUnknown;
}
@@ -100,6 +102,8 @@ static __u32 FromPixelFormat(VideoMode::PixelFormat pixelFormat) {
return V4L2_PIX_FMT_BGR24;
case VideoMode::kGray:
return V4L2_PIX_FMT_GREY;
case VideoMode::kUYVY:
return V4L2_PIX_FMT_UYVY;
default:
return 0;
}

View File

@@ -368,6 +368,12 @@ void UsbCameraImpl::ProcessFrame(IMFSample* videoSample,
tmpMat.total() * 2);
tmpMat.copyTo(dest->AsMat());
break;
case cs::VideoMode::PixelFormat::kUYVY:
tmpMat = cv::Mat(mode.height, mode.width, CV_8UC2, ptr, pitch);
dest = AllocImage(VideoMode::kUYVY, tmpMat.cols, tmpMat.rows,
tmpMat.total() * 2);
tmpMat.copyTo(dest->AsMat());
break;
default:
doFinalSet = false;
break;
@@ -472,6 +478,8 @@ static cs::VideoMode::PixelFormat GetFromGUID(const GUID& guid) {
return cs::VideoMode::PixelFormat::kMJPEG;
} else if (IsEqualGUID(guid, MFVideoFormat_RGB565)) {
return cs::VideoMode::PixelFormat::kRGB565;
} else if (IsEqualGUID(guid, MFVideoFormat_UYVY)) {
return cs::VideoMode::PixelFormat::kUYVY;
} else {
return cs::VideoMode::PixelFormat::kUnknown;
}