bool SavePng(std::string filename, const DepthImage& img) { // Open up a file for writing FILE* output = fopen(filename.c_str(), "wb"); if (output == NULL) { printf("Failed to open PNG file for writing (errno = %i)\n", errno); return false; } // Create a png pointer with the callbacks above png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, on_png_error, on_png_warn); if (png_ptr == NULL) { fprintf(stderr, "Failed to allocate png write_struct\n"); fclose(output); return false; } // Create an info pointer png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "Failed to create png info_struct"); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(output); return false; } // Set physical vars png_set_IHDR(png_ptr, info_ptr, img.cols(), img.rows(), 16, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_init_io(png_ptr, output); const float zmax = img.maxCoeff(); const float zmin = (img == -std::numeric_limits<float>::infinity()) .select(DepthImage::Constant(img.rows(), img.cols(), zmax), img) .minCoeff(); auto scaled = (zmax == zmin) ? DepthImage((img - zmin) + 65535) : DepthImage((img - zmin) * 65534 / (zmax - zmin) + 1); Eigen::Array<uint16_t, Eigen::Dynamic, Eigen::Dynamic> pixels = scaled.cast<uint16_t>().transpose(); std::vector<uint16_t*> rows; for (int i=pixels.cols() - 1; i >= 0; --i) { rows.push_back(pixels.data() + i * pixels.rows()); } png_set_rows(png_ptr, info_ptr, reinterpret_cast<png_bytepp>(&rows[0])); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, NULL); fclose(output); png_destroy_write_struct(&png_ptr, &info_ptr); return true; }
void MyKinect::ProcessDepth(const UINT16* pBuffer, int nWidth, int nHeight, USHORT nMinDepth, USHORT nMaxDepth) {//处理深度,并修复,产生掩码 #ifdef DEBUG MyTime mt; mt.Reset(); mt.Start(); #endif // Make sure we've received valid data if (m_pDepthRGBX && pBuffer && (nWidth == cDepthWidth) && (nHeight == cDepthHeight)) { depthFrames++; cout << "depthFrames第" << depthFrames << "帧" << endl; RGBQUAD* pRGBX = m_pDepthRGBX; const UINT16* pBufferEnd = pBuffer + (nWidth * nHeight); int k1 = 0, k2 = 0; int k3 = 0, k4 = 0; Mat inpaintResult;//修图结果 Mat inpaintMask;//掩码 Mat badMask;//错误点的掩码 badMask = Mat::zeros(Size(nWidth, nHeight), CV_8U); inpaintMask = Mat::zeros(Size(nWidth, nHeight), CV_8U); /*uchar * inpaintDataMask = inpaintMask.data; uchar * badMaskData = badMask.data;//标记当前帧 错误点掩码 uchar * depthMat_LastData= m_pDepthMat_Last.data; uchar * depthMat_LastDataMask = m_pDepthMat_LastMask.data;//前景的掩码 */ /* int a = m_pDepthMat_Last.channels(); int b = m_pDepthMat_LastMask.channels(); int c = badMask.channels(); int d = inpaintMask.channels(); cout << a << " " << b << " " << c << " " << d << endl; */ //考虑到mat字节对齐,改为for for (int i = 0; i < nHeight;i++) { uchar * inpaintDataMask = inpaintMask.ptr<uchar>(i); uchar * badMaskData = badMask.ptr<uchar>(i);//标记当前帧 错误点掩码 uchar * depthMat_LastData = m_pDepthMat_Last.ptr<uchar>(i); uchar * depthMat_LastDataMask = m_pDepthMat_LastMask.ptr<uchar>(i);//前景的掩码 for (int j = 0; j < nWidth;j++) { USHORT depth = *pBuffer; bool maskOfPixel = 0; if (depth <= 0)//must error pixels { depth = 0; badMaskData[j] = (uchar)255; maskOfPixel = 1; k1++; } if (depth > 4500) k2++; depth = depth >> 4;//如何最好的将 450 -- 5500映射到 0 -255里面 //有大量=0的点,2W多 , if (depth >= 255) {//掩码赋值 depth = 255; } BYTE intensity = static_cast<BYTE>(depth); //用上一帧修正 if (maskOfPixel) {//深度有误 k3++; //上一帧的修复只能对背景用,不能对运动的用 //if ((depthMat_LastDataMask[j]) == 0)//是背景 //重要的地方就是 人运动的边缘,而这都是前景区域了。 {//这两个是8u3c的 intensity = (depthMat_LastData[j*3]);//采用上一帧 } if (intensity == 0)// || intensity == 255))//结果表明 摄像头固定,有的点会一直错误 {//上一帧也是错误点,且没修复,接着修复 inpaintDataMask[j] = (uchar)255; k4++; } } pRGBX->rgbRed = intensity; pRGBX->rgbGreen = intensity; pRGBX->rgbBlue = intensity; ++pRGBX; ++pBuffer; } } // std::cout << setw(5)<< k1 << setw(5) << k2 <<"为0点:"<<setw(5)<<k3<<" 修正:"<<setw(5)<<k4<<" "<<" "<<std::endl ; //复制上一帧 // memcpy( m_pDepthRGBX_Last,m_pDepthRGBX, sizeof(RGBQUAD)*cDepthHeight*cDepthWidth); // Draw the data with OpenCV Mat DepthImage(nHeight, nWidth, CV_8UC4, m_pDepthRGBX); //imshow("orignal", DepthImage); //cvMoveWindow("orignal",0,0); Mat depthImageRGB; cvtColor(DepthImage,depthImageRGB,CV_RGBA2RGB); cv::inpaint(depthImageRGB, inpaintMask, inpaintResult, 3, CV_INPAINT_TELEA);// CV_INPAINT_NS);//空洞太大了效果不好 //使用了inpaint后,就是第一帧会修复,其他的都不会修复了。 // imshow("inpaint", inpaintResult); // cvMoveWindow("inpaint", 500, 0); //cvSmooth(&inpaintResult, &m_pDepthMat_Last);这是c格式的支持cvmat的,下面的才是c++的 // Mat blurMat; // blur(inpaintResult, blurMat, Size(3, 3), Point(-1, -1)); //Size( w,h ): // imshow("blur", blurMat); //cvMoveWindow("blur",500,500); //2015-5-10 晚 ,修改为缩小版 cv::resize(m_pDepthMat_Last, m_pDepthMat_Last_Resize, cv::Size(cDepthWidth_RESIZE, cDepthHeight_RESIZE)); //对 fuliye版本 调整位置 cv::GaussianBlur(inpaintResult, m_pDepthMat_Last, Size(3, 3), 0,0); //Size( w,h ): // m_pDepthMat_Last = inpaintResult.clone();//保存上一帧 // imshow("gaussianBlur", m_pDepthMat_Last); //cvMoveWindow("gaussianBlur",0,500); // cvMoveWindow("gaussianBlur", 0, 0); // cvWaitKey(1); // cout << "m_pDepthMat_Last :" << m_pDepthMat_Last.channels(); Mat foreMat;//提取前景 //m_pDepthBackProcess.process_Mog2(m_pDepthMat_Last, foreMat); // m_pDepthBackProcess.depthProcessBackGround(m_pDepthMat_Last, m_pDepthMat_LastMask); // m_pDepthBackProcess.testManyMethod(m_pDepthMat_Last, foreMat); m_pDepthBackProcess.depthProcessBackGround(m_pDepthMat_Last_Resize, m_pDepthMat_LastMask_Resize); /* 测试分割 ImageSegment iseg; m_pTempshow=iseg.regiongrowthIndepth3(m_pDepthMat_Last, m_pDepthMat_LastMask); */ /* if( (foreMat.rows !=0 )&& (foreMat.cols !=0)) { m_pDepthMat_LastMask = foreMat.clone();//保存前景的掩码 }*/ // cout <<"通道数目"<< inpaintResult.channels(); // BaseImageTools::SaveDepthImageToAVI(inpaintResult, nWidth, nHeight, depthWriter); // BaseImageTools::SaveDepthImageToAVI(inpaintResult, nWidth, nHeight, depthWriter2); //BaseImageTools::SaveDepthImageToAVI(DepthImage, nWidth, nHeight, depthWriter); /* Mat show = DepthImage.clone(); imshow("DepthImage2", show); */ }
bool ofxDepthImageSequence::loadSequence(string newSequenceDirectory){ ofDirectory sequenceList(newSequenceDirectory); if(!sequenceList.exists()){ ofLogError("ofxDepthImageSequence -- sequence directory " + newSequenceDirectory + " does not exist!"); return false; } if(sequenceLoaded){ images.clear(); sequenceLoaded = false; } sequenceList.allowExt("png"); int numFiles = sequenceList.listDir(); if(numFiles == 0){ ofLogError("ofxTLDepthImageSequence -- sequence directory " + newSequenceDirectory + " is empty!"); return false; } bool checkedForTimestamp = false; unsigned long firstFrameTimeOffset = 0; for(int i = 0; i < numFiles; i++){ //backwards compat... if(sequenceList.getName(i).find("poster") != string::npos){ ofLogWarning("discarding poster frame " + sequenceList.getPath(i) ); continue; } if(!checkedForTimestamp){ framesHaveTimestamps = sequenceList.getName(i).find("millis") != string::npos; checkedForTimestamp = true; ofLogVerbose("Frames have timestamps? " + string((framesHaveTimestamps ? "yes!" : "no :(")) ); } images.push_back( DepthImage() ); DepthImage& img = images[images.size()-1]; img.path = sequenceList.getPath(i); if(framesHaveTimestamps){ vector<string> split = ofSplitString(sequenceList.getName(i), "_", true, true); for(int l = 0; l < split.size(); l++){ if(split[l] == "millis"){ img.timestamp = ofToInt(split[l+1]); if(i == 0){ firstFrameTimeOffset = img.timestamp; } img.timestamp -= firstFrameTimeOffset; } } } images.push_back( img ); } //currentFrame = -1; if(framesHaveTimestamps){ durationInMillis = images[images.size()-1].timestamp; } ofLogVerbose("sequence is loaded " + ofToString( images.size() )); sequenceDirectory = newSequenceDirectory; sequenceLoaded = true; setFrame(0); updatePixels(); // startThread(); return true; }