Use the V channel to provide masking information, indicating invalid depths.

This commit is contained in:
Andrzej Kapolka 2013-07-30 13:42:29 -07:00
parent 3c437076a7
commit f8ba1c4be1
2 changed files with 52 additions and 20 deletions

View file

@ -569,9 +569,9 @@ void FrameGrabber::grabFrame() {
ydest[0] = (tl[redIndex] * Y_RED_WEIGHT + tl[1] * Y_GREEN_WEIGHT + tl[blueIndex] * Y_BLUE_WEIGHT) >> 8; ydest[0] = (tl[redIndex] * Y_RED_WEIGHT + tl[1] * Y_GREEN_WEIGHT + tl[blueIndex] * Y_BLUE_WEIGHT) >> 8;
ydest[1] = (tr[redIndex] * Y_RED_WEIGHT + tr[1] * Y_GREEN_WEIGHT + tr[blueIndex] * Y_BLUE_WEIGHT) >> 8; ydest[1] = (tr[redIndex] * Y_RED_WEIGHT + tr[1] * Y_GREEN_WEIGHT + tr[blueIndex] * Y_BLUE_WEIGHT) >> 8;
ydest[ENCODED_FACE_WIDTH] = (bl[redIndex] * Y_RED_WEIGHT + bl[greenIndex] * ydest[vpxImage.stride[0]] = (bl[redIndex] * Y_RED_WEIGHT + bl[greenIndex] *
Y_GREEN_WEIGHT + bl[blueIndex] * Y_BLUE_WEIGHT) >> 8; Y_GREEN_WEIGHT + bl[blueIndex] * Y_BLUE_WEIGHT) >> 8;
ydest[ENCODED_FACE_WIDTH + 1] = (br[redIndex] * Y_RED_WEIGHT + br[greenIndex] * ydest[vpxImage.stride[0] + 1] = (br[redIndex] * Y_RED_WEIGHT + br[greenIndex] *
Y_GREEN_WEIGHT + br[blueIndex] * Y_BLUE_WEIGHT) >> 8; Y_GREEN_WEIGHT + br[blueIndex] * Y_BLUE_WEIGHT) >> 8;
ydest += 2; ydest += 2;
@ -616,26 +616,37 @@ void FrameGrabber::grabFrame() {
glm::mix(mean, _smoothedMeanFaceDepth, DEPTH_OFFSET_SMOOTHING); glm::mix(mean, _smoothedMeanFaceDepth, DEPTH_OFFSET_SMOOTHING);
// convert from 11 to 8 bits for preview/local display // convert from 11 to 8 bits for preview/local display
const double EIGHT_BIT_MIDPOINT = 128.0; const uchar EIGHT_BIT_MIDPOINT = 128;
double depthOffset = EIGHT_BIT_MIDPOINT - _smoothedMeanFaceDepth; double depthOffset = EIGHT_BIT_MIDPOINT - _smoothedMeanFaceDepth;
depth.convertTo(_grayDepthFrame, CV_8UC1, 1.0, depthOffset); depth.convertTo(_grayDepthFrame, CV_8UC1, 1.0, depthOffset);
// likewise for the encoded representation // likewise for the encoded representation
uchar* yline = (uchar*)_encodedFace.data() + vpxImage.stride[0] * ENCODED_FACE_HEIGHT; uchar* yline = vpxImage.planes[0] + vpxImage.stride[0] * ENCODED_FACE_HEIGHT;
src = _faceDepth.ptr<ushort>(); uchar* vline = vpxImage.planes[1] + vpxImage.stride[1] * (ENCODED_FACE_HEIGHT / 2);
const char EIGHT_BIT_MAXIMUM = 255; const uchar EIGHT_BIT_MAXIMUM = 255;
for (int i = 0; i < ENCODED_FACE_HEIGHT; i++) { for (int i = 0; i < ENCODED_FACE_HEIGHT; i += 2) {
uchar* ydest = yline; uchar* ydest = yline;
for (int j = 0; j < ENCODED_FACE_WIDTH; j++) { uchar* vdest = vline;
ushort depth = *src++; for (int j = 0; j < ENCODED_FACE_WIDTH; j += 2) {
if (depth == ELEVEN_BIT_MINIMUM) { ushort tl = *_faceDepth.ptr<ushort>(i, j);
*ydest++ = EIGHT_BIT_MAXIMUM; ushort tr = *_faceDepth.ptr<ushort>(i, j + 1);
ushort bl = *_faceDepth.ptr<ushort>(i + 1, j);
} else { ushort br = *_faceDepth.ptr<ushort>(i + 1, j + 1);
*ydest++ = saturate_cast<uchar>(depth + depthOffset);
} uchar mask = EIGHT_BIT_MIDPOINT;
ydest[0] = (tl == ELEVEN_BIT_MINIMUM) ? (mask = EIGHT_BIT_MAXIMUM) : saturate_cast<uchar>(tl + depthOffset);
ydest[1] = (tr == ELEVEN_BIT_MINIMUM) ? (mask = EIGHT_BIT_MAXIMUM) : saturate_cast<uchar>(tr + depthOffset);
ydest[vpxImage.stride[0]] = (bl == ELEVEN_BIT_MINIMUM) ?
(mask = EIGHT_BIT_MAXIMUM) : saturate_cast<uchar>(bl + depthOffset);
ydest[vpxImage.stride[0] + 1] = (br == ELEVEN_BIT_MINIMUM) ?
(mask = EIGHT_BIT_MAXIMUM) : saturate_cast<uchar>(br + depthOffset);
ydest += 2;
*vdest++ = mask;
} }
yline += vpxImage.stride[0]; yline += vpxImage.stride[0] * 2;
vline += vpxImage.stride[1];
} }
} }

View file

@ -147,10 +147,31 @@ int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) {
if (image->d_h > imageHeight) { if (image->d_h > imageHeight) {
// if the height is greater than the width, we have depth data // if the height is greater than the width, we have depth data
depth.create(imageHeight, image->d_w, CV_8UC1); depth.create(imageHeight, image->d_w, CV_8UC1);
uchar* src = image->planes[0] + image->stride[0] * imageHeight; uchar* yline = image->planes[0] + image->stride[0] * imageHeight;
for (int i = 0; i < imageHeight; i++) { uchar* vline = image->planes[1] + image->stride[1] * (imageHeight / 2);
memcpy(depth.ptr(i), src, image->d_w); const uchar EIGHT_BIT_MAXIMUM = 255;
src += image->stride[0]; const uchar MASK_THRESHOLD = 192;
for (int i = 0; i < imageHeight; i += 2) {
uchar* ysrc = yline;
uchar* vsrc = vline;
for (int j = 0; j < image->d_w; j += 2) {
if (*vsrc++ >= MASK_THRESHOLD) {
*depth.ptr(i, j) = EIGHT_BIT_MAXIMUM;
*depth.ptr(i, j + 1) = EIGHT_BIT_MAXIMUM;
*depth.ptr(i + 1, j) = EIGHT_BIT_MAXIMUM;
*depth.ptr(i + 1, j + 1) = EIGHT_BIT_MAXIMUM;
} else {
*depth.ptr(i, j) = ysrc[0];
*depth.ptr(i, j + 1) = ysrc[1];
*depth.ptr(i + 1, j) = ysrc[image->stride[0]];
*depth.ptr(i + 1, j + 1) = ysrc[image->stride[0] + 1];
}
ysrc += 2;
}
yline += image->stride[0] * 2;
vline += image->stride[1];
} }
} }
QMetaObject::invokeMethod(this, "setFrame", Q_ARG(cv::Mat, color), QMetaObject::invokeMethod(this, "setFrame", Q_ARG(cv::Mat, color),