#ifdef HAVE_INTELPERC #include "cap_intelperc.hpp" namespace cv { ///////////////// IntelPerCStreamBase ////////////////// IntelPerCStreamBase::IntelPerCStreamBase() : m_profileIdx(-1) , m_frameIdx(0) , m_timeStampStartNS(0) { } IntelPerCStreamBase::~IntelPerCStreamBase() { } bool IntelPerCStreamBase::isValid() { return (m_device.IsValid() && m_stream.IsValid()); } bool IntelPerCStreamBase::grabFrame() { if (!m_stream.IsValid()) return false; if (-1 == m_profileIdx) { if (!setProperty(CV_CAP_PROP_INTELPERC_PROFILE_IDX, 0)) return false; } PXCSmartSP sp; m_pxcImage.ReleaseRef(); if (PXC_STATUS_NO_ERROR > m_stream->ReadStreamAsync(&m_pxcImage, &sp)) return false; if (PXC_STATUS_NO_ERROR > sp->Synchronize()) return false; if (0 == m_timeStampStartNS) m_timeStampStartNS = m_pxcImage->QueryTimeStamp(); m_timeStamp = (double)((m_pxcImage->QueryTimeStamp() - m_timeStampStartNS) / 10000); m_frameIdx++; return true; } int IntelPerCStreamBase::getProfileIDX() const { return m_profileIdx; } double IntelPerCStreamBase::getProperty(int propIdx) const { double ret = 0.0; switch (propIdx) { case CV_CAP_PROP_INTELPERC_PROFILE_COUNT: ret = (double)m_profiles.size(); break; case CV_CAP_PROP_FRAME_WIDTH : if ((0 <= m_profileIdx) && (m_profileIdx < m_profiles.size())) ret = (double)m_profiles[m_profileIdx].imageInfo.width; break; case CV_CAP_PROP_FRAME_HEIGHT : if ((0 <= m_profileIdx) && (m_profileIdx < m_profiles.size())) ret = (double)m_profiles[m_profileIdx].imageInfo.height; break; case CV_CAP_PROP_FPS : if ((0 <= m_profileIdx) && (m_profileIdx < m_profiles.size())) { ret = ((double)m_profiles[m_profileIdx].frameRateMin.numerator / (double)m_profiles[m_profileIdx].frameRateMin.denominator + (double)m_profiles[m_profileIdx].frameRateMax.numerator / (double)m_profiles[m_profileIdx].frameRateMax.denominator) / 2.0; } break; case CV_CAP_PROP_POS_FRAMES: ret = (double)m_frameIdx; break; case CV_CAP_PROP_POS_MSEC: ret = m_timeStamp; break; }; return ret; } bool IntelPerCStreamBase::setProperty(int propIdx, double propVal) { bool isSet = false; switch (propIdx) { case CV_CAP_PROP_INTELPERC_PROFILE_IDX: { int propValInt = (int)propVal; if (0 > propValInt) { m_profileIdx = propValInt; isSet = true; } else if (propValInt < m_profiles.size()) { if (m_profileIdx != propValInt) { m_profileIdx = propValInt; if (m_stream.IsValid()) m_stream->SetProfile(&m_profiles[m_profileIdx]); m_frameIdx = 0; m_timeStampStartNS = 0; } isSet = true; } } break; }; return isSet; } bool IntelPerCStreamBase::initDevice(PXCSession *session) { if (NULL == session) return false; pxcStatus sts = PXC_STATUS_NO_ERROR; PXCSession::ImplDesc templat; memset(&templat,0,sizeof(templat)); templat.group = PXCSession::IMPL_GROUP_SENSOR; templat.subgroup= PXCSession::IMPL_SUBGROUP_VIDEO_CAPTURE; for (int modidx = 0; PXC_STATUS_NO_ERROR <= sts; modidx++) { PXCSession::ImplDesc desc; sts = session->QueryImpl(&templat, modidx, &desc); if (PXC_STATUS_NO_ERROR > sts) break; PXCSmartPtr capture; sts = session->CreateImpl(&desc, &capture); if (!capture.IsValid()) continue; /* enumerate devices */ for (int devidx = 0; PXC_STATUS_NO_ERROR <= sts; devidx++) { PXCSmartPtr device; sts = capture->CreateDevice(devidx, &device); if (PXC_STATUS_NO_ERROR <= sts) { m_device = device.ReleasePtr(); return true; } } } return false; } void IntelPerCStreamBase::initStreamImpl(PXCImage::ImageType type) { if (!m_device.IsValid()) return; pxcStatus sts = PXC_STATUS_NO_ERROR; /* enumerate streams */ for (int streamidx = 0; PXC_STATUS_NO_ERROR <= sts; streamidx++) { PXCCapture::Device::StreamInfo sinfo; sts = m_device->QueryStream(streamidx, &sinfo); if (PXC_STATUS_NO_ERROR > sts) break; if (PXCCapture::VideoStream::CUID != sinfo.cuid) continue; if (type != sinfo.imageType) continue; sts = m_device->CreateStream(streamidx, &m_stream); if (PXC_STATUS_NO_ERROR == sts) break; m_stream.ReleaseRef(); } } bool IntelPerCStreamBase::validProfile(const PXCCapture::VideoStream::ProfileInfo& /*pinfo*/) { return true; } void IntelPerCStreamBase::enumProfiles() { m_profiles.clear(); if (!m_stream.IsValid()) return; pxcStatus sts = PXC_STATUS_NO_ERROR; for (int profidx = 0; PXC_STATUS_NO_ERROR <= sts; profidx++) { PXCCapture::VideoStream::ProfileInfo pinfo; sts = m_stream->QueryProfile(profidx, &pinfo); if (PXC_STATUS_NO_ERROR > sts) break; if (validProfile(pinfo)) m_profiles.push_back(pinfo); } } ///////////////// IntelPerCStreamImage ////////////////// IntelPerCStreamImage::IntelPerCStreamImage() { } IntelPerCStreamImage::~IntelPerCStreamImage() { } bool IntelPerCStreamImage::initStream(PXCSession *session) { if (!initDevice(session)) return false; initStreamImpl(PXCImage::IMAGE_TYPE_COLOR); if (!m_stream.IsValid()) return false; enumProfiles(); return true; } double IntelPerCStreamImage::getProperty(int propIdx) const { switch (propIdx) { case CV_CAP_PROP_BRIGHTNESS: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_BRIGHTNESS, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_CONTRAST: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_CONTRAST, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_SATURATION: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_SATURATION, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_HUE: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_HUE, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_GAMMA: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_GAMMA, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_SHARPNESS: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_SHARPNESS, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_GAIN: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_GAIN, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_BACKLIGHT: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_BACK_LIGHT_COMPENSATION, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_EXPOSURE: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_COLOR_EXPOSURE, &fret)) return (double)fret; return 0.0; } break; //Add image stream specific properties } return IntelPerCStreamBase::getProperty(propIdx); } bool IntelPerCStreamImage::setProperty(int propIdx, double propVal) { switch (propIdx) { case CV_CAP_PROP_BRIGHTNESS: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_BRIGHTNESS, (float)propVal)); } break; case CV_CAP_PROP_CONTRAST: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_CONTRAST, (float)propVal)); } break; case CV_CAP_PROP_SATURATION: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_SATURATION, (float)propVal)); } break; case CV_CAP_PROP_HUE: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_HUE, (float)propVal)); } break; case CV_CAP_PROP_GAMMA: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_GAMMA, (float)propVal)); } break; case CV_CAP_PROP_SHARPNESS: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_SHARPNESS, (float)propVal)); } break; case CV_CAP_PROP_GAIN: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_GAIN, (float)propVal)); } break; case CV_CAP_PROP_BACKLIGHT: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_BACK_LIGHT_COMPENSATION, (float)propVal)); } break; case CV_CAP_PROP_EXPOSURE: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_COLOR_EXPOSURE, (float)propVal)); } break; //Add image stream specific properties } return IntelPerCStreamBase::setProperty(propIdx, propVal); } bool IntelPerCStreamImage::retrieveAsOutputArray(cv::OutputArray image) { if (!m_pxcImage.IsValid()) return false; PXCImage::ImageInfo info; m_pxcImage->QueryInfo(&info); PXCImage::ImageData data; m_pxcImage->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::COLOR_FORMAT_RGB24, &data); if (PXCImage::SURFACE_TYPE_SYSTEM_MEMORY != data.type) return false; cv::Mat temp(info.height, info.width, CV_8UC3, data.planes[0], data.pitches[0]); temp.copyTo(image); m_pxcImage->ReleaseAccess(&data); return true; } ///////////////// IntelPerCStreamDepth ////////////////// IntelPerCStreamDepth::IntelPerCStreamDepth() { } IntelPerCStreamDepth::~IntelPerCStreamDepth() { } bool IntelPerCStreamDepth::initStream(PXCSession *session) { if (!initDevice(session)) return false; initStreamImpl(PXCImage::IMAGE_TYPE_DEPTH); if (!m_stream.IsValid()) return false; enumProfiles(); return true; } double IntelPerCStreamDepth::getProperty(int propIdx) const { switch (propIdx) { case CV_CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_DEPTH_LOW_CONFIDENCE_VALUE, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_DEPTH_SATURATION_VALUE, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD: { if (!m_device.IsValid()) return 0.0; float fret = 0.0f; if (PXC_STATUS_NO_ERROR == m_device->QueryProperty(PXCCapture::Device::PROPERTY_DEPTH_CONFIDENCE_THRESHOLD, &fret)) return (double)fret; return 0.0; } break; case CV_CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ: { if (!m_device.IsValid()) return 0.0f; PXCPointF32 ptf; if (PXC_STATUS_NO_ERROR == m_device->QueryPropertyAsPoint(PXCCapture::Device::PROPERTY_DEPTH_FOCAL_LENGTH, &ptf)) return (double)ptf.x; return 0.0; } break; case CV_CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT: { if (!m_device.IsValid()) return 0.0f; PXCPointF32 ptf; if (PXC_STATUS_NO_ERROR == m_device->QueryPropertyAsPoint(PXCCapture::Device::PROPERTY_DEPTH_FOCAL_LENGTH, &ptf)) return (double)ptf.y; return 0.0; } break; //Add depth stream sepcific properties } return IntelPerCStreamBase::getProperty(propIdx); } bool IntelPerCStreamDepth::setProperty(int propIdx, double propVal) { switch (propIdx) { case CV_CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_DEPTH_LOW_CONFIDENCE_VALUE, (float)propVal)); } break; case CV_CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_DEPTH_SATURATION_VALUE, (float)propVal)); } break; case CV_CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD: { if (!m_device.IsValid()) return false; return (PXC_STATUS_NO_ERROR == m_device->SetProperty(PXCCapture::Device::PROPERTY_DEPTH_CONFIDENCE_THRESHOLD, (float)propVal)); } break; //Add depth stream sepcific properties } return IntelPerCStreamBase::setProperty(propIdx, propVal); } bool IntelPerCStreamDepth::retrieveDepthAsOutputArray(cv::OutputArray image) { return retriveFrame(CV_16SC1, 0, image); } bool IntelPerCStreamDepth::retrieveIRAsOutputArray(cv::OutputArray image) { return retriveFrame(CV_16SC1, 1, image); } bool IntelPerCStreamDepth::retrieveUVAsOutputArray(cv::OutputArray image) { return retriveFrame(CV_32FC2, 2, image); } bool IntelPerCStreamDepth::validProfile(const PXCCapture::VideoStream::ProfileInfo& pinfo) { return (PXCImage::COLOR_FORMAT_DEPTH == pinfo.imageInfo.format); } bool IntelPerCStreamDepth::retriveFrame(int type, int planeIdx, cv::OutputArray frame) { if (!m_pxcImage.IsValid()) return false; PXCImage::ImageInfo info; m_pxcImage->QueryInfo(&info); PXCImage::ImageData data; m_pxcImage->AcquireAccess(PXCImage::ACCESS_READ, &data); if (PXCImage::SURFACE_TYPE_SYSTEM_MEMORY != data.type) return false; cv::Mat temp(info.height, info.width, type, data.planes[planeIdx], data.pitches[planeIdx]); temp.copyTo(frame); m_pxcImage->ReleaseAccess(&data); return true; } ///////////////// VideoCapture_IntelPerC ////////////////// VideoCapture_IntelPerC::VideoCapture_IntelPerC() : m_contextOpened(false) { pxcStatus sts = PXCSession_Create(&m_session); if (PXC_STATUS_NO_ERROR > sts) return; m_contextOpened = m_imageStream.initStream(m_session); m_contextOpened &= m_depthStream.initStream(m_session); } VideoCapture_IntelPerC::~VideoCapture_IntelPerC(){} double VideoCapture_IntelPerC::getProperty(int propIdx) const { double propValue = 0; int purePropIdx = propIdx & ~CV_CAP_INTELPERC_GENERATORS_MASK; if (CV_CAP_INTELPERC_IMAGE_GENERATOR == (propIdx & CV_CAP_INTELPERC_GENERATORS_MASK)) { propValue = m_imageStream.getProperty(purePropIdx); } else if (CV_CAP_INTELPERC_DEPTH_GENERATOR == (propIdx & CV_CAP_INTELPERC_GENERATORS_MASK)) { propValue = m_depthStream.getProperty(purePropIdx); } else { propValue = m_depthStream.getProperty(purePropIdx); } return propValue; } bool VideoCapture_IntelPerC::setProperty(int propIdx, double propVal) { bool isSet = false; int purePropIdx = propIdx & ~CV_CAP_INTELPERC_GENERATORS_MASK; if (CV_CAP_INTELPERC_IMAGE_GENERATOR == (propIdx & CV_CAP_INTELPERC_GENERATORS_MASK)) { isSet = m_imageStream.setProperty(purePropIdx, propVal); } else if (CV_CAP_INTELPERC_DEPTH_GENERATOR == (propIdx & CV_CAP_INTELPERC_GENERATORS_MASK)) { isSet = m_depthStream.setProperty(purePropIdx, propVal); } else { isSet = m_depthStream.setProperty(purePropIdx, propVal); } return isSet; } bool VideoCapture_IntelPerC::grabFrame() { if (!isOpened()) return false; bool isGrabbed = false; if (m_depthStream.isValid()) isGrabbed = m_depthStream.grabFrame(); if ((m_imageStream.isValid()) && (-1 != m_imageStream.getProfileIDX())) isGrabbed &= m_imageStream.grabFrame(); return isGrabbed; } bool VideoCapture_IntelPerC::retrieveFrame(int outputType, cv::OutputArray frame) { switch (outputType) { case CV_CAP_INTELPERC_DEPTH_MAP: return m_depthStream.retrieveDepthAsOutputArray(frame); case CV_CAP_INTELPERC_UVDEPTH_MAP: return m_depthStream.retrieveUVAsOutputArray(frame); case CV_CAP_INTELPERC_IR_MAP: return m_depthStream.retrieveIRAsOutputArray(frame); case CV_CAP_INTELPERC_IMAGE: return m_imageStream.retrieveAsOutputArray(frame); } return false; } int VideoCapture_IntelPerC::getCaptureDomain() { return CV_CAP_INTELPERC; } bool VideoCapture_IntelPerC::isOpened() const { return m_contextOpened; } } #endif //HAVE_INTELPERC