1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Switch network camera to OpenCV

This commit is contained in:
Tux3 / Mlkj / !Lev.uXFMLA 2014-08-29 14:20:32 +02:00
parent f4b1b64ae6
commit 6348976df7
3 changed files with 41 additions and 141 deletions

View File

@ -94,11 +94,6 @@ void Camera::unsuscribe()
}
}
QVideoFrame Camera::getLastVideoFrame()
{
return lastFrame;
}
Mat Camera::getLastFrame()
{
Mat frame;
@ -174,148 +169,67 @@ bool Camera::isFormatSupported(const QVideoSurfaceFormat& format) const
}
}
QImage Camera::getLastImage()
{
if (!lastFrame.map(QAbstractVideoBuffer::ReadOnly))
Mat3b src = getLastFrame();
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
for (int y = 0; y < src.rows; ++y)
{
qWarning() << "Camera::getLastImage: Error maping last frame";
return QImage();
const cv::Vec3b *srcrow = src[y];
QRgb *destrow = (QRgb*)dest.scanLine(y);
for (int x = 0; x < src.cols; ++x)
destrow[x] = qRgba(srcrow[x][2], srcrow[x][1], srcrow[x][0], 255);
}
int w = lastFrame.width(), h = lastFrame.height();
int bpl = lastFrame.bytesPerLine(), cxbpl = bpl/2;
QImage img(w, h, QImage::Format_RGB32);
if (frameFormat == QVideoFrame::Format_YUV420P)
{
uint8_t* yData = lastFrame.bits();
uint8_t* uData = yData + (bpl * h);
uint8_t* vData = uData + (bpl * h / 4);
for (int i = 0; i< h; i++)
{
uint32_t* scanline = (uint32_t*)img.scanLine(i);
for (int j=0; j < bpl; j++)
{
uint8_t Y = yData[i*bpl + j];
uint8_t U = uData[i/2*cxbpl + j/2];
uint8_t V = vData[i/2*cxbpl + j/2];
uint8_t R, G, B;
fromYCbCrToRGB(Y, U, V, R, G, B);
scanline[j] = (0xFF<<24) + (R<<16) + (G<<8) + B;
}
}
}
else if (frameFormat == QVideoFrame::Format_YV12)
{
uint8_t* yData = lastFrame.bits();
uint8_t* vData = yData + (bpl * h);
uint8_t* uData = vData + (bpl * h / 4);
for (int i = 0; i< h; i++)
{
uint32_t* scanline = (uint32_t*)img.scanLine(i);
for (int j=0; j < bpl; j++)
{
uint8_t Y = yData[i*bpl + j];
uint8_t U = uData[i/2*cxbpl + j/2];
uint8_t V = vData[i/2*cxbpl + j/2];
uint8_t R, G, B;
fromYCbCrToRGB(Y, U, V, R, G, B);
scanline[j] = (0xFF<<24) + (R<<16) + (G<<8) + B;
}
}
}
else if (frameFormat == QVideoFrame::Format_RGB32)
{
memcpy(img.bits(), lastFrame.bits(), bpl*h);
}
lastFrame.unmap();
return img;
return dest;
}
vpx_image Camera::getLastVPXImage()
{
Mat3b frame = getLastFrame();
vpx_image img;
img.w = img.h = 0;
if (!lastFrame.isValid())
return img;
if (!lastFrame.map(QAbstractVideoBuffer::ReadOnly))
{
qWarning() << "Camera::getLastVPXImage: Error maping last frame";
return img;
}
int w = lastFrame.width(), h = lastFrame.height();
int bpl = lastFrame.bytesPerLine();
int w = frame.size().width, h = frame.size().height;
vpx_img_alloc(&img, VPX_IMG_FMT_I420, w, h, 1); // I420 == YUV420P, same as YV12 with U and V switched
if (frameFormat == QVideoFrame::Format_YUV420P)
{
uint8_t* yData = lastFrame.bits();
uint8_t* uData = yData + (bpl * h);
uint8_t* vData = uData + (bpl * h / 4);
img.planes[VPX_PLANE_Y] = yData;
img.planes[VPX_PLANE_U] = uData;
img.planes[VPX_PLANE_V] = vData;
}
else if (frameFormat == QVideoFrame::Format_YV12)
{
uint8_t* yData = lastFrame.bits();
uint8_t* uData = yData + (bpl * h);
uint8_t* vData = uData + (bpl * h / 4);
img.planes[VPX_PLANE_Y] = yData;
img.planes[VPX_PLANE_U] = vData;
img.planes[VPX_PLANE_V] = uData;
}
else if (frameFormat == QVideoFrame::Format_RGB32 || frameFormat == QVideoFrame::Format_ARGB32)
{
qWarning() << "Camera::getLastVPXImage: Using experimental RGB32 conversion code";
uint8_t* rgb = lastFrame.bits();
size_t i=0, j=0;
qWarning() << "Camera::getLastVPXImage: Using experimental RGB32 conversion code" << w << ","<<h;
size_t i=0, j=0;
for( int line = 0; line < h; ++line )
for( int line = 0; line < h; ++line )
{
const cv::Vec3b *srcrow = frame[line];
if( !(line % 2) )
{
if( !(line % 2) )
for( int x = 0; x < w; x += 2 )
{
for( int x = 0; x < w; x += 2 )
{
uint8_t r = rgb[4 * i + 1];
uint8_t g = rgb[4 * i + 2];
uint8_t b = rgb[4 * i + 3];
uint8_t r = srcrow[x][2];
uint8_t g = srcrow[x][1];
uint8_t b = srcrow[x][0];
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
img.planes[VPX_PLANE_U][j] = ((-38*r + -74*g + 112*b) >> 8) + 128;
img.planes[VPX_PLANE_V][j] = ((112*r + -94*g + -18*b) >> 8) + 128;
i++;
j++;
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
img.planes[VPX_PLANE_U][j] = ((-38*r + -74*g + 112*b) >> 8) + 128;
img.planes[VPX_PLANE_V][j] = ((112*r + -94*g + -18*b) >> 8) + 128;
i++;
j++;
r = rgb[4 * i + 1];
g = rgb[4 * i + 2];
b = rgb[4 * i + 3];
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
i++;
}
r = srcrow[x+1][2];
g = srcrow[x+1][1];
b = srcrow[x+1][0];
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
i++;
}
else
}
else
{
for( int x = 0; x < w; x += 1 )
{
for( int x = 0; x < w; x += 1 )
{
uint8_t r = rgb[4 * i + 1];
uint8_t g = rgb[4 * i + 2];
uint8_t b = rgb[4 * i + 3];
uint8_t r = srcrow[x][2];
uint8_t g = srcrow[x][1];
uint8_t b = srcrow[x][0];
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
i++;
}
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
i++;
}
}
}
lastFrame.unmap();
return img;
}

View File

@ -41,7 +41,6 @@ public:
void suscribe(); ///< Call this once before trying to get frames
void unsuscribe(); ///< Call this once when you don't need frames anymore
cv::Mat getLastFrame(); ///< Get the last captured frame
QVideoFrame getLastVideoFrame(); ///< Get the last captured frame
QImage getLastImage(); ///< Convert the last frame to a QImage (can be expensive !)
vpx_image getLastVPXImage(); ///< Convert the last frame to a vpx_image (can be expensive !)
bool isFormatSupported(const QVideoSurfaceFormat & format) const;

View File

@ -62,22 +62,9 @@ void SelfCamView::showEvent(QShowEvent* event)
event->accept();
}
QImage Mat2QImage(const cv::Mat3b &src) {
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
for (int y = 0; y < src.rows; ++y) {
const cv::Vec3b *srcrow = src[y];
QRgb *destrow = (QRgb*)dest.scanLine(y);
for (int x = 0; x < src.cols; ++x) {
destrow[x] = qRgba(srcrow[x][2], srcrow[x][1], srcrow[x][0], 255);
}
}
return dest;
}
void SelfCamView::updateDisplay()
{
Mat frame = cam->getLastFrame();
displayLabel->setPixmap(QPixmap::fromImage(Mat2QImage(frame)));
cam->getLastVPXImage();
displayLabel->setPixmap(QPixmap::fromImage(cam->getLastImage()));
}