PowertfDialog::PowertfDialog(cv::Mat& img, QWidget *parent) : QDialog(parent) { r = 1; c = 1; b = 0; img.copyTo(image); pimage = &img; rSlider = new QSlider(Qt::Horizontal); rSlider->setRange(0,10); rSlider->setValue(r); cSlider = new QSlider(Qt::Horizontal); cSlider->setRange(0,10); cSlider->setValue(c); bSlider = new QSlider(Qt::Horizontal); bSlider->setRange(0,10); bSlider->setValue(b); rSBx = new QSpinBox(); rSBx->setRange(0,10); rSBx->setValue(r); cSBx = new QSpinBox(); cSBx->setRange(0,10); cSBx->setValue(c); bSBx = new QSpinBox(); bSBx->setRange(0,10); bSBx->setValue(b); connect(rSlider,SIGNAL(valueChanged(int)),this,SLOT(rChanged(int))); connect(cSlider,SIGNAL(valueChanged(int)),this,SLOT(cChanged(int))); connect(bSlider,SIGNAL(valueChanged(int)),this,SLOT(bChanged(int))); connect(rSlider,SIGNAL(valueChanged(int)),rSBx,SLOT(setValue(int))); connect(cSlider,SIGNAL(valueChanged(int)),cSBx,SLOT(setValue(int))); connect(bSlider,SIGNAL(valueChanged(int)),bSBx,SLOT(setValue(int))); connect(rSBx,SIGNAL(valueChanged(int)),this,SLOT(rChanged(int))); connect(cSBx,SIGNAL(valueChanged(int)),this,SLOT(cChanged(int))); connect(bSBx,SIGNAL(valueChanged(int)),this,SLOT(bChanged(int))); connect(rSBx,SIGNAL(valueChanged(int)),rSlider,SLOT(setValue(int))); connect(cSBx,SIGNAL(valueChanged(int)),cSlider,SLOT(setValue(int))); connect(bSBx,SIGNAL(valueChanged(int)),bSlider,SLOT(setValue(int))); rLabel = new QLabel(tr("r")); cLabel = new QLabel(tr("c")); bLabel = new QLabel(tr("b")); okButton = new QPushButton(tr("&OK")); okButton->setDefault(true); okButton->setEnabled(true); connect(okButton, SIGNAL(clicked()), this, SLOT(okClicked())); closeButton = new QPushButton(tr("&Close")); connect(closeButton, SIGNAL(clicked()), this, SLOT(closePowertf())); QHBoxLayout *rLayout = new QHBoxLayout; rLayout->addWidget(rLabel); rLayout->addWidget(rSlider); rLayout->addWidget(rSBx); QHBoxLayout *cLayout = new QHBoxLayout; cLayout->addWidget(cLabel); cLayout->addWidget(cSlider); cLayout->addWidget(cSBx); QHBoxLayout *bLayout = new QHBoxLayout; bLayout->addWidget(bLabel); bLayout->addWidget(bSlider); bLayout->addWidget(bSBx); QVBoxLayout *leftLayout = new QVBoxLayout; leftLayout->addLayout(rLayout); leftLayout->addLayout(cLayout); leftLayout->addLayout(bLayout); QVBoxLayout *rightLayout = new QVBoxLayout; rightLayout->addWidget(okButton); rightLayout->addWidget(closeButton); rightLayout->addStretch(); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addLayout(leftLayout); mainLayout->addLayout(rightLayout); setLayout(mainLayout); setWindowTitle(tr("Power Tranform")); setFixedHeight(sizeHint().height()); }
//general processing function of UVDisparity based function cv::Mat UVDisparity::Process(cv::Mat& img_L, cv::Mat& disp_sgbm, VisualOdometryStereo& vo, cv::Mat& xyz, cv::Mat& roi_mask, cv::Mat& ground_mask, double& pitch1, double& pitch2) { cv::Mat mask_moving; calVDisparity(disp_sgbm,xyz); //sequentially estimate pitch angles by Kalman Filter vector<cv::Mat> pitch_measures; pitch_measures = Pitch_Classify(xyz,ground_mask); pitch1_KF->predict(); pitch1_KF->correct(pitch_measures[0]); pitch2_KF->predict(); pitch2_KF->correct(pitch_measures[1]); pitch1 = pitch_measures[0].at<float>(0); pitch2 = pitch_measures[1].at<float>(0); //Improve 3D reconstruction results by pitch angles correct3DPoints(xyz,roi_,pitch1_KF->statePost.at<float>(0),pitch2_KF->statePost.at<float>(0)); //set image ROI according to ROI3D (ROI within a 3D space) setImageROI(xyz, roi_mask); //filter inliers and outliers filterInOut(img_L,roi_mask,disp_sgbm,vo,pitch1); //calculate Udisparity image calUDisparity(disp_sgbm,xyz,roi_mask,ground_mask); //using sigmoid function to adjust Udisparity image for segmentation double scale = 0.02, range = 32; adjustUdisIntense(scale,range); //Find all possible segmentation findAllMasks(vo,img_L,xyz,roi_mask); if(masks_.size()>0) { //merge overlapped masks mergeMasks(); //improve the segments by inliers verifyByInliers(vo,img_L); } //perform segmentation in disparity image segmentation(disp_sgbm,img_L,roi_mask,mask_moving); //demonstration cv::Mat img_show; img_L.copyTo(img_show,mask_moving); cv::imshow("moving",img_show); cv::waitKey(1); masks_.clear(); return mask_moving; }
static void dominantTransforms(const cv::Mat &img, std::vector <cv::Matx33f> &transforms, const int nTransform, const int psize) { /** Walsh-Hadamard Transformation **/ std::vector <cv::Mat> channels; cv::split(img, channels); int cncase = std::max(img.channels() - 2, 0); const int np[] = {cncase == 0 ? 12 : (cncase == 1 ? 16 : 10), cncase == 0 ? 12 : (cncase == 1 ? 04 : 02), cncase == 0 ? 00 : (cncase == 1 ? 04 : 02), cncase == 0 ? 00 : (cncase == 1 ? 00 : 10)}; for (int i = 0; i < img.channels(); ++i) rgb2whs(channels[i], channels[i], np[i], psize); cv::Mat whs; // Walsh-Hadamard series cv::merge(channels, whs); KDTree <float, 24> kdTree(whs, 16, 32); std::vector <int> annf( whs.total(), 0 ); /** Propagation-assisted kd-tree search **/ for (int i = 0; i < whs.rows; ++i) for (int j = 0; j < whs.cols; ++j) { double dist = std::numeric_limits <double>::max(); int current = i*whs.cols + j; int dy[] = {0, 1, 0}, dx[] = {0, 0, 1}; for (int k = 0; k < int( sizeof(dy)/sizeof(int) ); ++k) if (i - dy[k] >= 0 && j - dx[k] >= 0) { int neighbor = (i - dy[k])*whs.cols + (j - dx[k]); int leafIdx = k == 0 ? neighbor : annf[neighbor] + dy[k]*whs.cols + dx[k]; kdTree.updateDist(leafIdx, current, annf[i*whs.cols + j], dist); } } /** Local maxima extraction **/ cv::Mat_<double> annfHist(2*whs.rows - 1, 2*whs.cols - 1, 0.0), _annfHist(2*whs.rows - 1, 2*whs.cols - 1, 0.0); for (size_t i = 0; i < annf.size(); ++i) ++annfHist( (annf[i] - int(i))/whs.cols + whs.rows - 1, (annf[i] - int(i))%whs.cols + whs.cols - 1 ); cv::GaussianBlur( annfHist, annfHist, cv::Size(0, 0), std::sqrt(2.0), 0.0, cv::BORDER_CONSTANT); cv::dilate( annfHist, _annfHist, cv::Matx<uchar, 9, 9>::ones() ); std::vector < std::pair<double, int> > amount; std::vector <cv::Point2i> shiftM; for (int i = 0, t = 0; i < annfHist.rows; ++i) { double *pAnnfHist = annfHist.ptr<double>(i); double *_pAnnfHist = _annfHist.ptr<double>(i); for (int j = 0; j < annfHist.cols; ++j) if ( pAnnfHist[j] != 0 && pAnnfHist[j] == _pAnnfHist[j] ) { amount.push_back( std::make_pair(pAnnfHist[j], t++) ); shiftM.push_back( cv::Point2i(j - whs.cols + 1, i - whs.rows + 1) ); } } std::partial_sort( amount.begin(), amount.begin() + nTransform, amount.end(), std::greater< std::pair<double, int> >() ); transforms.resize(nTransform); for (int i = 0; i < nTransform; ++i) { int idx = amount[i].second; transforms[i] = cv::Matx33f(1, 0, float(shiftM[idx].x), 0, 1, float(shiftM[idx].y), 0, 0, 1 ); } }
/* * objective : get the gray level map of the input image and rescale it to the range [0-255] */ static void rescaleGrayLevelMat(const cv::Mat &inputMat, cv::Mat &outputMat, const float histogramClippingLimit) { // adjust output matrix wrt the input size but single channel std::cout<<"Input image rescaling with histogram edges cutting (in order to eliminate bad pixels created during the HDR image creation) :"<<std::endl; //std::cout<<"=> image size (h,w,channels) = "<<inputMat.size().height<<", "<<inputMat.size().width<<", "<<inputMat.channels()<<std::endl; //std::cout<<"=> pixel coding (nbchannel, bytes per channel) = "<<inputMat.elemSize()/inputMat.elemSize1()<<", "<<inputMat.elemSize1()<<std::endl; // rescale between 0-255, keeping floating point values cv::normalize(inputMat, outputMat, 0.0, 255.0, cv::NORM_MINMAX); // extract a 8bit image that will be used for histogram edge cut cv::Mat intGrayImage; if (inputMat.channels()==1) { outputMat.convertTo(intGrayImage, CV_8U); }else { cv::Mat rgbIntImg; outputMat.convertTo(rgbIntImg, CV_8UC3); cv::cvtColor(rgbIntImg, intGrayImage, cv::COLOR_BGR2GRAY); } // get histogram density probability in order to cut values under above edges limits (here 5-95%)... usefull for HDR pixel errors cancellation cv::Mat dst, hist; int histSize = 256; calcHist(&intGrayImage, 1, 0, cv::Mat(), hist, 1, &histSize, 0); cv::Mat normalizedHist; normalize(hist, normalizedHist, 1, 0, cv::NORM_L1, CV_32F); // normalize histogram so that its sum equals 1 double min_val, max_val; minMaxLoc(normalizedHist, &min_val, &max_val); //std::cout<<"Hist max,min = "<<max_val<<", "<<min_val<<std::endl; // compute density probability cv::Mat denseProb=cv::Mat::zeros(normalizedHist.size(), CV_32F); denseProb.at<float>(0)=normalizedHist.at<float>(0); int histLowerLimit=0, histUpperLimit=0; for (int i=1;i<normalizedHist.size().height;++i) { denseProb.at<float>(i)=denseProb.at<float>(i-1)+normalizedHist.at<float>(i); //std::cout<<normalizedHist.at<float>(i)<<", "<<denseProb.at<float>(i)<<std::endl; if ( denseProb.at<float>(i)<histogramClippingLimit) histLowerLimit=i; if ( denseProb.at<float>(i)<1-histogramClippingLimit) histUpperLimit=i; } // deduce min and max admitted gray levels float minInputValue = (float)histLowerLimit/histSize*255; float maxInputValue = (float)histUpperLimit/histSize*255; std::cout<<"=> Histogram limits " <<"\n\t"<<histogramClippingLimit*100<<"% index = "<<histLowerLimit<<" => normalizedHist value = "<<denseProb.at<float>(histLowerLimit)<<" => input gray level = "<<minInputValue <<"\n\t"<<(1-histogramClippingLimit)*100<<"% index = "<<histUpperLimit<<" => normalizedHist value = "<<denseProb.at<float>(histUpperLimit)<<" => input gray level = "<<maxInputValue <<std::endl; //drawPlot(denseProb, "input histogram density probability", histLowerLimit, histUpperLimit); drawPlot(normalizedHist, "input histogram", histLowerLimit, histUpperLimit); // rescale image range [minInputValue-maxInputValue] to [0-255] outputMat-=minInputValue; outputMat*=255.0/(maxInputValue-minInputValue); // cut original histogram and back project to original image cv::threshold( outputMat, outputMat, 255.0, 255.0, 2 ); //THRESH_TRUNC, clips values above 255 cv::threshold( outputMat, outputMat, 0.0, 0.0, 3 ); //THRESH_TOZERO, clips values under 0 }
bool CaffeFeatExtractor<Dtype>::extract_singleFeat_1D(cv::Mat &image, vector<Dtype> &features, float (×)[2]) { times[0] = 0.0f; times[1] = 0.0f; // Check input image if (image.empty()) { std::cout << "CaffeFeatExtractor::extract_singleFeat_1D(): empty imMat!" << std::endl; return false; } // Start timing cudaEvent_t startPrep, stopPrep, startNet, stopNet; if (timing) { cudaEventCreate(&startPrep); cudaEventCreate(&startNet); cudaEventCreate(&stopPrep); cudaEventCreate(&stopNet); cudaEventRecord(startPrep, NULL); cudaEventRecord(startNet, NULL); } // Prepare Caffe // Set the GPU/CPU mode for Caffe (here in order to be thread-safe) if (gpu_mode) { Caffe::set_mode(Caffe::GPU); Caffe::SetDevice(device_id); } else { Caffe::set_mode(Caffe::CPU); } // Initialize labels to zero int label = 0; // Get pointer to data layer to set the input caffe::shared_ptr<MemoryDataLayer<Dtype> > memory_data_layer = boost::dynamic_pointer_cast<caffe::MemoryDataLayer<Dtype> >(feature_extraction_net->layers()[0]); // Set batch size to 1 if (memory_data_layer->batch_size()!=1) { memory_data_layer->set_batch_size(1); std::cout << "CaffeFeatExtractor::extract_singleFeat_1D(): BATCH SIZE = " << memory_data_layer->batch_size() << std::endl; } // Image preprocessing // The image passed to AddMatVector must be same size as the mean image // If not, it is resized: // if it is downsampled, an anti-aliasing Gaussian Filter is applied if (image.rows != mean_height || image.cols != mean_height) { if (image.rows > mean_height || image.cols > mean_height) { cv::resize(image, image, cv::Size(mean_height, mean_width), 0, 0, CV_INTER_LANCZOS4); } else { cv::resize(image, image, cv::Size(mean_height, mean_width), 0, 0, CV_INTER_LINEAR); } } memory_data_layer->AddMatVector(vector<cv::Mat>(1, image),vector<int>(1,label)); size_t num_features = blob_names.size(); if(num_features!=1) { std::cout << "CaffeFeatExtractor::extract_singleFeat_1D(): Error! The list of features to be extracted has not size one!" << std::endl; return false; } if (timing) { // Record the stop event cudaEventRecord(stopPrep, NULL); // Wait for the stop event to complete cudaEventSynchronize(stopPrep); cudaEventElapsedTime(times, startPrep, stopPrep); } // Run network and retrieve features! // depending on your net's architecture, the blobs will hold accuracy and/or labels, etc std::vector<Blob<Dtype>*> results = feature_extraction_net->Forward(); const caffe::shared_ptr<Blob<Dtype> > feature_blob = feature_extraction_net->blob_by_name(blob_names[0]); int batch_size = feature_blob->num(); // should be 1 if (batch_size!=1) { std::cout << "CaffeFeatExtractor::extract_singleFeat_1D(): Error! Retrieved more than one feature, exiting..." << std::endl; return -1; } int feat_dim = feature_blob->count(); // should be equal to: count/num=channels*width*height if (feat_dim!=feature_blob->channels()) { std::cout << "CaffeFeatExtractor::extract_singleFeat_1D(): Attention! The feature is not 1D: unrolling according to Caffe's order (i.e. channel, height, width)" << std::endl; } features.insert(features.end(), feature_blob->mutable_cpu_data() + feature_blob->offset(0), feature_blob->mutable_cpu_data() + feature_blob->offset(0) + feat_dim); if (timing) { // Record the stop event cudaEventRecord(stopNet, NULL); // Wait for the stop event to complete cudaEventSynchronize(stopNet); cudaEventElapsedTime(times+1, startNet, stopNet); } return true; }
/** @brief 色相だけのヒストグラムを計算する @param src ヒストグラムを計算する画像 */ void HIST::calcHistgramHue(cv::Mat &src) { if(src.data == NULL) return; // グラフのデータ間の距離 stepH = (double)ui.histgramH->width()/180; cv::cvtColor(src, src, cv::COLOR_BGR2HSV); int count[180]; int max = 0; // 初期化 for (int i = 0; i < 180; i++) count[i] = 0; // 色相の各値の個数を取得 for (int j = 0; j < src.cols; j++) for (int i = 0; i < src.rows; i++) // ほぼ白(彩度≒0)は無視 if(src.data[i * src.step + j * src.elemSize() + 1] > 3) count[src.data[i * src.step + j * src.elemSize()]]++; cv::cvtColor(src, src, cv::COLOR_HSV2BGR); // スケーリング定数(一番多い個数)の取得 for (int i = 0; i < 180; i++) if(max < count[i]) max = count[i]; // スケーリング double histgram[180]; for (int i = 0; i < 180; i++) histgram[i] = (double)count[i] / max * 200; /** 簡易グラフ作成 **/ int gWidth = 180 * stepH; int gHeight = 200; // 格子画像 cv::Mat baseGraph(gHeight, gWidth, CV_8UC3, cv::Scalar(255, 255, 255)); // 色相のヒストグラム画像 cv::Mat hueGraph(gHeight, gWidth, CV_8UC3, cv::Scalar(255, 255, 255)); // 上記2つを乗算ブレンディングした最終的に描画する画像 cv::Mat graph(gHeight, gWidth, CV_8UC3, cv::Scalar(255, 255, 255)); cv::cvtColor(hueGraph, hueGraph, cv::COLOR_BGR2HSV); for (int j = 0; j < hueGraph.rows; j++){ for (int i = 0; i < hueGraph.cols; i++){ hueGraph.data[j * hueGraph.step + i * hueGraph.elemSize() + 0] = (int)((double)i/stepH); hueGraph.data[j * hueGraph.step + i * hueGraph.elemSize() + 1] = 220; hueGraph.data[j * hueGraph.step + i * hueGraph.elemSize() + 2] = 180; } } cv::cvtColor(hueGraph, hueGraph, cv::COLOR_HSV2BGR); // 横のメモリ for (int i = 0; i < 20; i++) if(!(i%4)) cv::line(baseGraph, cv::Point(0, i*10), cv::Point(gWidth, i*10), cv::Scalar(180, 180, 180), 2); else cv::line(baseGraph, cv::Point(0, i*10), cv::Point(gWidth, i*10), cv::Scalar(200, 200, 200), 1); // 色相のグラフ for (int i = 0; i < 180; i++) cv::line(hueGraph, cv::Point((int)(i*stepH), 0), cv::Point((int)(i*stepH), (int)histgram[i]), cv::Scalar(180, 180, 180), 2); // 折れ線 for (int i = 0; i < 180; i++) cv::line(hueGraph, cv::Point((int)(i*stepH), (int)histgram[i]), cv::Point((int)((i+1)*stepH), (int)histgram[i+1]), cv::Scalar(90, 90, 90), 2, CV_AA); // 合成 blend(baseGraph, hueGraph, graph, blendType::MULTI); // 上下を反転 cv::flip(graph, graph, 0); drawForQtLabel(graph, ui.histgramH, false); }
bool ParallaxErrorAnalysis_GradientPatch(const cv::Mat& img1,const shape& img1_shp, const cv::Mat& img2, const shape& img2_shp, const cv::Mat& img2_original, const cv::Mat& H, const cv::Size2i& img_size ,double& res_error) { vector<cv::Point2f> overlap_points; for(int r = 0 ; r < img_size.height; r++) { for(int c = 0; c < img_size.width; c++) { shape t_img1_shape = img1_shp; shape t_img2_shape = img2_shp; cv::Point2f t_point(c, r); if(t_img1_shape.isInShape(c, r) && t_img2_shape.isInShape(c, r) ) { // 记下这些点 overlap_points.push_back(t_point); } } } // 找到这些点在 img2_original 上的对应点 cv::Mat Hn = H.inv(); vector<cv::Point2f> correPoints_ori(overlap_points.size(),*new cv::Point2f); cv::perspectiveTransform(overlap_points, correPoints_ori, Hn); // 两个参数都要是 vector<cv::Point2f> f 不能是 i //检测有没有越界的 /*ofstream Dout("2.txt",ios::out); for(int i = 0; i < correPoints_ori.size(); i++) { if(correPoints_ori[i].x < 0 || correPoints_ori[i].x > img2_original.cols || correPoints_ori[i].y < 0 || correPoints_ori[i].y > img2_original.rows) { Dout<< correPoints_ori[i].x << " "<<correPoints_ori[i].y << endl; } } Dout.clear(); Dout.close();*/ // 计算 error res_error = 0; cv::Mat img_blend; vector<cv::Mat> imgs; vector<shape> shapes; imgs.push_back(img1); imgs.push_back(img2); shapes.push_back(img1_shp); shapes.push_back(img2_shp); blending_all(imgs, shapes, img_size, img_blend); // 求 Iij 和 Ij 的 Gradient 图 cv::Mat img_blend_G; cv::Mat img2_original_G; gradientGray(img_blend, img_blend_G); gradientGray(img2_original, img2_original_G); // test 测试 到底有哪些点 不一样。 vector<cv::Point2f> err_points_img2; vector<uchar> err_img2; // Gradient 图求 error double res = 0; for(int i = 0; i < overlap_points.size(); i++) { uchar Gray1 = img_blend_G.at<uchar>(overlap_points[i]); uchar Gray2 = img2_original_G.at<uchar>(correPoints_ori[i]); int tr = abs(Gray1 - Gray2); //if(tr != 0) // 很多是相差就1,这样基本一样的 //{ // res += tr; //} if(tr >= 5) // 很多是相差就1,这样基本一样的 { res += tr; err_points_img2.push_back(correPoints_ori[i]); err_img2.push_back(tr); } } res_error = res; // 测试的图 // 新建一张 img_size 的黑色图 IplImage* st_img = cvCreateImage(img2_original.size(), IPL_DEPTH_8U, 3); for(int i = 0; i < st_img->height; i++) { uchar *ptrImage = (uchar*)(st_img->imageData + i * st_img->widthStep); for (int j = 0; j < st_img->width; j++) { ptrImage[3 * j + 0]=0; ptrImage[3 * j + 1]=0; ptrImage[3 * j + 2]=0; } } cv::Mat test_img = st_img; for(int i = 0; i < err_points_img2.size(); i++) { test_img.at<Vec3b>(err_points_img2[i])[2] = err_img2[i]; } imwrite("error_ori.jpg",img2_original); imwrite("error_test.jpg",test_img); //end test return true; }
//void CutoutImage::rotateMat (const cv::Mat srcMat ,cv::Mat &dstMat,const cv::Mat colorMat) void CutoutImage::rotateMat (const cv::Mat srcMat ,cv::Mat &dstMat,const cv::Mat colorMat, const cv::Mat wholeImage, cv::Mat &wholeImageCut) { std::vector<std::vector<cv::Point>> contours; std::vector<cv::Vec4f> lineVector; cv::Mat aMat = srcMat.clone(); cv::findContours(aMat, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); cv::Mat showMat = cv::Mat(aMat.rows,aMat.cols,CV_8UC3,cv::Scalar(0,0,0)); //dstMat = aMat.clone(); dstMat = cv::Mat(srcMat.size(), CV_8UC4, cv::Scalar(0,0,0,0)); std::vector<cv::Rect> nailRect; cv::Mat wholeImageRotate; for(int i = 0;i<(int)contours.size();i++) { if(contours[i].size() > 5) { cv::RotatedRect tmp = cv::minAreaRect(contours[i]); //ellipses.push_back(temp); cv::drawContours(showMat, contours, i, cv::Scalar(255,0,0), 1, 8); cv::ellipse(showMat, tmp, cv::Scalar(0,255,255), 2, 8); //cv::line(<#cv::Mat &img#>, <#Point pt1#>, <#Point pt2#>, <#const Scalar &color#>) cv::rectangle(showMat, tmp.boundingRect(), cv::Scalar(255,255,0),1,8); //imshow("Ellipses", showMat); float rotAngle = tmp.angle; tmp.angle = 0; //cv::circle(showMat, cv::Point(tmp.boundingRect().x,tmp.boundingRect().y) , 2, cv::Scalar(0,0,255)); if(tmp.boundingRect().width > tmp.boundingRect().height) { tmp.angle = 90; rotAngle = rotAngle - 90; } cv::rectangle(showMat, tmp.boundingRect(), cv::Scalar(255,255,0),1,8); nailRect.push_back(tmp.boundingRect()); cv::ellipse(showMat, tmp, cv::Scalar(255,255,255), 2, 8); //imshow("Ellipses", showMat); //cv::Mat rotMat = cv::Mat(2,3,CV_32FC1); cv::Mat rotMat = cv::getRotationMatrix2D(tmp.center,rotAngle, 1); //cv::transform(srcMat, dstMat, rotMat); cv::warpAffine(colorMat, dstMat, rotMat, cv::Size(std::max(srcMat.rows,srcMat.cols),std::max(srcMat.rows,srcMat.cols)), CV_INTER_NN); cv::warpAffine(wholeImage.clone(), wholeImageRotate, rotMat, cv::Size(std::max(srcMat.rows,srcMat.cols),std::max(srcMat.rows,srcMat.cols)), CV_INTER_LANCZOS4); //cv::imshow("RRRRRR", dstMat); } else { // cv::drawContours(showMat, contours, i, cv::Scalar(255,255,255), -1, 8); // imshow("Ellipses", showMat); } } cv::RNG rng; //随机数 int rows = dstMat.rows; int cols = dstMat.cols; // printf(" b cutImageByRect rows = %d \n",rows); // printf(" b cutImageByRect cols = %d \n",cols); int lx = cols; int rx = 0; int ty = rows; int by = 0; cv::Mat grayDst; cv::cvtColor(dstMat, grayDst, CV_BGRA2GRAY); for(int y = 0; y<rows; y++ ){ uchar *grayDstRowsData = grayDst.ptr<uchar>(y); for(int x = 0; x<cols; x++ ){ if(grayDstRowsData[x] != 0 ) { if(x<lx){ lx = x; } if(x>rx){ rx = x; } if(y<ty){ ty = y; } if(y>by){ by = y; } } } } //扩大一下截图范围 if(lx - 10 >= 0) lx = lx - 10; if(rx + 10 <= cols - 1) rx = rx + 10; if(ty - 10 >= 0) ty = ty - 10; if(by + 10 <= rows - 1) by = by + 10; //cv::Point lt = cv::Point(lx,ty); //cv::Point rb = cv::Point(rx,by); cv::Rect cutRect = *new cv::Rect; cutRect.x = lx; cutRect.y = ty; cutRect.width = rx - lx + 1; cutRect.height = by - ty + 1; std::cout<< cutRect <<std::endl; cv::Mat cutDst; cv::Mat wholeImageRotateBGRA; cutImageByRect(dstMat, cutRect, cutDst); //截图 addAlphaChannle(wholeImageRotate, wholeImageRotateBGRA); cutImageByRect(wholeImageRotateBGRA, cutRect, wholeImageCut); //截图 dstMat = cutDst.clone(); //cv::rectangle(dstMat, lt, rb, cv::Scalar(0,0,255,0)); //cv::imshow("RRRRRR", dstMat); }
/* 将输入的二值图边缘平滑,用锐利边缘抠取输入的彩色图,然后再将彩色图与平滑边缘的图进行融合 */ void CutoutImage::filterImageEdgeAndBlurMerge( const cv::Mat colorMat, const cv::Mat bitMat, cv::Mat &dstMat ) { cv::Mat aBitMat = bitMat.clone(); cv::Mat aColorMat = colorMat.clone(); cv::Mat filterMat; //CutoutImage::filterImage(aBitMat, filterMat); //使预模糊区域大于正常区域 filterMat = aBitMat; //使预模糊区域与正常区域一样大 std::cout<<"aColorMat channels = " <<aColorMat.channels()<<std::endl; int blockSize = 5; int constValue = 10; // cv::adaptiveThreshold( filterMat, filterMat, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, blockSize, constValue ); cv::threshold(filterMat, filterMat, 1, 255, CV_THRESH_BINARY ); //jiangbo test cv::Mat tmpMMat; //CutoutImage::smoothContours( filterMat, tmpMMat ); int rows = aBitMat.rows; int cols = aBitMat.cols; //扣取范围较大的彩色图,并进行模糊,主要需要其边缘部分数据 cv::Mat cutBigColorMat = cv::Mat( rows , cols, CV_8UC3, cv::Scalar(255,255,255) ); for (int y = 0; y < rows; y++) { uchar *filterCutMatRowData = filterMat.ptr<uchar>(y); uchar *colorMatRowData = aColorMat.ptr<uchar>(y); uchar *cutBigColorMatRowData = cutBigColorMat.ptr<uchar>(y); for (int x = 0; x < cols; x++) { if(filterCutMatRowData[x] != 0){ cutBigColorMatRowData[x*3] = colorMatRowData[x*3]; cutBigColorMatRowData[x*3 + 1] = colorMatRowData[x*3 + 1]; cutBigColorMatRowData[x*3 + 2] = colorMatRowData[x*3 + 2]; } } } cv::Mat cutBigColorMatFilter; //CutoutImage::filterImage(cutBigColorMat, cutBigColorMatFilter); CutoutImage::filterImageForEdgeBlur(cutBigColorMat, cutBigColorMatFilter); cv::Mat bgrFilterMat; cv::cvtColor(filterMat, bgrFilterMat, CV_GRAY2BGR); cv::Mat smoothMask; CutoutImage::smoothContours(colorMat, bgrFilterMat, 21 , tmpMMat, smoothMask); cv::Mat fooRusultMat = cv::Mat( rows , cols, CV_8UC3, cv::Scalar(0,0,0) ); cv::Mat testEdgeData= cv::Mat( rows , cols, CV_8UC3, cv::Scalar(0,0,0) ); //融合 for(int y = 0; y < rows; y++){ uchar *aBitMatRowData = aBitMat.ptr<uchar>(y); uchar *colorMatRowData = aColorMat.ptr<uchar>(y); uchar *cutBigColorMatRowData = cutBigColorMatFilter.ptr<uchar>(y); uchar *fooRusultMatRowData = fooRusultMat.ptr<uchar>(y); uchar *testEdgeDataRowData = testEdgeData.ptr<uchar>(y); for(int x = 0; x < cols; x++){ if(aBitMatRowData[x] != 0){ fooRusultMatRowData[x*3] = colorMatRowData[x*3]; fooRusultMatRowData[x*3 + 1] = colorMatRowData[x*3 + 1]; fooRusultMatRowData[x*3 + 2] = colorMatRowData[x*3 + 2]; } if(cutBigColorMatRowData[x*3] != 255 || cutBigColorMatRowData[x*3 + 1] != 255 || cutBigColorMatRowData[x*3 + 2] != 255){ if(aBitMatRowData[x] == 0){ fooRusultMatRowData[x*3] = cutBigColorMatRowData[x*3]; fooRusultMatRowData[x*3 + 1] = cutBigColorMatRowData[x*3 + 1]; fooRusultMatRowData[x*3 + 2] = cutBigColorMatRowData[x*3 + 2]; testEdgeDataRowData[x*3] = cutBigColorMatRowData[x*3]; testEdgeDataRowData[x*3 + 1] = cutBigColorMatRowData[x*3 + 1]; testEdgeDataRowData[x*3 + 2] = cutBigColorMatRowData[x*3 + 2]; } } } } }
void CutoutImage::setColorImg(cv::Mat colorImg) { _cloverGrabCut->setImage(colorImg); inputColorImageSize = colorImg.size(); }
void CutoutImage::processImageCreatMask( std::vector<cv::Point> mouseSlideRegionDiscrete , const cv::Mat srcMat, cv::Mat &dstMat, int lineWidth, int expandWidth ) { cv::Mat showMat;// = srcMat.clone(); cv::cvtColor(srcMat, showMat, CV_BGR2GRAY); cv::Mat showMergeColorImg = srcMat.clone(); cv::Mat seedStoreMat = dstMat; //seedStoreMat 在外部存储了本次操作所生成的全部种子点。 mouseSlideRegion.clear(); cv::Size matSize = *new cv::Size; matSize.width = showMat.cols; matSize.height = showMat.rows; CutoutImage::drawLineAndMakePointSet(mouseSlideRegionDiscrete,matSize,lineWidth,mouseSlideRegion); int lx = showMat.cols,rx = 0,ty = showMat.rows,by = 0; //求画线范围 for(int i = 0;i<(int)mouseSlideRegion.size();i++) { //std::cout<<"point = "<< mouseSlideRegion[i]<<std::endl; //cv::circle(showMatClone, mouseSlideRegion[i], 0.5, cv::Scalar(255)); //绘制现实点 //最左面点x,最右面点x,最上面点y,最下面点y if(mouseSlideRegion[i].x < lx) { lx = mouseSlideRegion[i].x; } if(mouseSlideRegion[i].x > rx) { rx = mouseSlideRegion[i].x; } if(mouseSlideRegion[i].y <ty ) { ty = mouseSlideRegion[i].y; } if(mouseSlideRegion[i].y > by){ by = mouseSlideRegion[i].y; } //CvPoint forePtsCvPoint = } std::cout<<" lx " << lx << " rx " << rx << " ty " << ty << " by " << by <<std::endl; std::cout<<" orgMat cols " <<showMat.cols<< "orgMat rows " << showMat.rows <<std::endl; if( lx - expandWidth >= 0 ) lx = lx - expandWidth; if( rx + expandWidth <= showMat.cols - 1 ) rx = rx + expandWidth; if( ty - expandWidth >= 0) ty = ty - expandWidth; if( by + expandWidth <= showMat.rows - 1 ) by = by + expandWidth; std::cout<<" lx " << lx << " rx " << rx << " ty " << ty << " by " << by <<std::endl; cv::Point ltP = cv::Point(lx,ty); cv::Point rtP = cv::Point(rx,ty); cv::Point lbP = cv::Point(lx,by); cv::Point rbP = cv::Point(rx,by); //要截取的图形 int rectMatRow = by - ty + 1; int rectMatCol = rx - lx + 1; cv::Mat recMat = cv::Mat (rectMatRow,rectMatCol,CV_8UC1,cv::Scalar(0)); //cv::rectangle(showMatClone, ltP, rbP, cv::Scalar(255),1); //画图形 cv::Mat mouseSlideSeedStoreMat = cv::Mat(rectMatRow,rectMatCol,CV_8UC1,cv::Scalar(0)); for(int y = 0;y<rectMatRow;y++){ uchar *rectMatLineData = recMat.ptr<uchar>(y); uchar *orgMatLineData = showMat.ptr<uchar>(ty+y); uchar *msssMatLineData = mouseSlideSeedStoreMat.ptr<uchar>(y); uchar *ssMatLineData = seedStoreMat.ptr<uchar>(ty+y); for(int x = 0; x < rectMatCol; x++){ rectMatLineData[x] = orgMatLineData[lx+x]; msssMatLineData[x] = ssMatLineData[lx + x]; } } //cutMat = recMat.clone(); //cv::imshow("mouseSlideSeedStoreMat", mouseSlideSeedStoreMat); cv::Mat bitMat; int blockSize = 25; int constValue = 10; cv::adaptiveThreshold(recMat, bitMat, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, blockSize, constValue); cv::Mat filterImg; CutoutImage::filterImage(recMat,filterImg); cv::Mat nextImg = filterImg.clone(); cv::Mat regionGrowMat; CutoutImage::rectRegionGrow( mouseSlideRegion, ltP, filterImg, mouseSlideSeedStoreMat ,regionGrowMat); // cv::imshow("regionGrowMat", regionGrowMat); cv::Mat mergeMat; CutoutImage::mergeProcess(regionGrowMat,mergeMat); // cv::imshow("mergeMat", mergeMat); CutoutImage::storeSeed(seedStoreMat,mergeMat,ltP); // seedStoreMat 需要扣取的mask // cv::imshow("seedStoreMat", seedStoreMat); //cv::imshow("showMat", showMatClone); cv::Mat colorMergeMat; CutoutImage::colorDispResultWithFullSeedMat(showMergeColorImg,seedStoreMat); }
/// <summary> /// Calculates for each image patch the focus measure value. Result is a vector of Patches (see class Patch). /// If the image is binary, the relative foreground (foreground pixel / patchSize) and the weight is stored for each Patch. /// </summary> /// <param name="fm">The specified focuse measure method fm (e.g. Brenner).</param> /// <param name="fmImg">The image fmImg to calculate the focus measure on. If empty, the src image is taken.</param> /// <param name="binary">if set to <c>true</c> [binary] the input image is binary, specifying the foreground image. The foreground area and the weight is saved to the image patch</param> /// <returns>True if the focus measure could be computed, false otherwise.</returns> bool FocusEstimation::compute(FocusMeasure fm, cv::Mat fmImg, bool binary) { cv::Mat fImg = fmImg; if (fImg.empty()) fImg = mSrcImg; if (fImg.empty()) return false; if (fmImg.channels() != 1 || fImg.depth() != CV_32F) return false; BasicFM fmClass; double f; mFmPatches.clear(); for (int row = 0; row < fImg.rows; row += (mWindowSize+mSplitSize)) { for (int col = 0; col < fImg.cols; col += (mWindowSize+mSplitSize)) { cv::Range rR(row, cv::min(row + mWindowSize, fImg.rows)); cv::Range cR(col, cv::min(col + mWindowSize, fImg.cols)); cv::Mat tile = fImg(rR, cR); fmClass.setImg(tile); switch (fm) { case dsc::FocusEstimation::BREN: f = fmClass.computeBREN(); break; case dsc::FocusEstimation::GLVA: f = fmClass.computeGLVA(); break; case dsc::FocusEstimation::GLVN: f = fmClass.computeGLVN(); break; case dsc::FocusEstimation::GLLV: f = fmClass.computeGLLV(); break; case dsc::FocusEstimation::GRAT: f = fmClass.computeGRAT(); break; case dsc::FocusEstimation::GRAS: f = fmClass.computeGRAS(); break; case dsc::FocusEstimation::LAPE: f = fmClass.computeLAPE(); break; case dsc::FocusEstimation::LAPV: f = fmClass.computeLAPV(); break; case dsc::FocusEstimation::ROGR: f = fmClass.computeROGR(); break; default: f = -1; break; } Patch r(cv::Point(col, row), mWindowSize, mWindowSize, f); if (binary) { cv::Scalar relArea = cv::sum(tile); r.setArea(relArea[0]); relArea[0] = relArea[0] / (double)(mWindowSize * mWindowSize); //area completely written with text ~ 0.1 //normalize to 1 relArea[0] *= 10.0; r.setWeight(relArea[0]); //weight with sigmoid function //-6: shift sigmoid to the right //*10: scale normalized Area //double a = 10.0; //double b = -6.0; //double weight = 1.0 / (1 + std::exp(-(relArea[0] * a + b))); //r.setWeight(weight); } mFmPatches.push_back(r); } } return true; }
cv::Point EyeTracker::computePupilLocation(cv::Mat eye) { cv::Mat x_gradient = computeMaxGradient(eye); cv::Mat y_gradient = computeMaxGradient(eye.t()).t(); cv::Mat magnitude = computeMagnitudes(x_gradient, y_gradient); double gradient_threshold = computeDynamicThreshold(magnitude, 50.0); resizeAndRender(magnitude, "sample_eye_gradient_mag"); DEBUG("Gradient threshold: " << gradient_threshold); for (int y = 0; y < eye.rows; ++y) { double* x_row = x_gradient.ptr<double>(y); double* y_row = y_gradient.ptr<double>(y); const double* mag_row = magnitude.ptr<double>(y); for (int x = 0; x < eye.cols; ++x) { double gX = x_row[x]; double gY = y_row[x]; double m = mag_row[x]; if (m > gradient_threshold) { x_row[x] = gX / m; y_row[x] = gY / m; } else { x_row[x] = 0; y_row[x] = 0; } } } resizeAndRender(x_gradient, "sample_eye_gradient_x"); resizeAndRender(y_gradient, "sample_eye_gradient_y"); cv::Mat weight; cv::GaussianBlur(eye, weight, cv::Size(5, 5), 0, 0); for (int y = 0; y < weight.rows; ++y) { unsigned char* row = weight.ptr<unsigned char>(y); for (int x = 0; x < weight.cols; ++x) { row[x] = (255 - row[x]); } } resizeAndRender(weight, "sample_eye_weight"); cv::Mat out_sum = cv::Mat::zeros(eye.rows, eye.cols, CV_64F); for (int y = 0; y < weight.rows; ++y) { const double* Xr = x_gradient.ptr<double>(y); const double* Yr = y_gradient.ptr<double>(y); for (int x = 0; x < weight.cols; ++x) { double gX = Xr[x]; double gY = Yr[x]; if (gX == 0.0 && gY == 0.0) { continue; } test_center(x, y, weight, gX, gY, out_sum); } } double gradients_num = weight.rows * weight.cols; cv::Mat out; out_sum.convertTo(out, CV_32F, 1.0 / gradients_num); cv::Point max_point; double max_value; cv::minMaxLoc(out, NULL, &max_value, NULL, &max_point); cv::Mat flood_clone; double flood_thresh = max_value * 0.97; cv::threshold(out, flood_clone, flood_thresh, 0.0f, cv::THRESH_TOZERO); cv::Mat mask = floodKillEdges(flood_clone); cv::minMaxLoc(out, NULL, &max_value, NULL, &max_point, mask); resizeAndRender(mask, "sample_eye_mask"); resizeAndRender(out, "sample_eye_possible_centers"); return max_point; }
void Depth::calcPointCloud( const cv::Mat& input_disparity, const cv::Mat& left_image, const double baseline, const double focal_length, const int cx, const int cy, pcl::PointCloud<pcl::PointXYZRGB>* pointcloud, pcl::PointCloud<pcl::PointXYZRGB>* freespace_pointcloud) { pointcloud->clear(); freespace_pointcloud->clear(); if (left_image.depth() != CV_8U) { ROS_ERROR( "Pointcloud generation is currently only supported on 8 bit images"); return; } cv::Mat disparity_filled, input_valid; bulidFilledDisparityImage(input_disparity, &disparity_filled, &input_valid); int side_bound = sad_window_size_ / 2; // build pointcloud for (int y_pixels = side_bound; y_pixels < input_disparity.rows - side_bound; ++y_pixels) { for (int x_pixels = side_bound + min_disparity_ + num_disparities_; x_pixels < input_disparity.cols - side_bound; ++x_pixels) { const uint8_t& is_valid = input_valid.at<uint8_t>(y_pixels, x_pixels); const int16_t& input_value = input_disparity.at<int16_t>(y_pixels, x_pixels); const int16_t& filled_value = disparity_filled.at<int16_t>(y_pixels, x_pixels); bool freespace; double disparity_value; // if the filled disparity is valid it must be a freespace ray if (filled_value < std::numeric_limits<int16_t>::max()) { disparity_value = static_cast<double>(filled_value); freespace = true; } // else it is a normal ray else if (is_valid) { disparity_value = static_cast<double>(input_value); freespace = false; } else { continue; } pcl::PointXYZRGB point; // the 16* is needed as opencv stores disparity maps as 16 * the true // values point.z = (16 * focal_length * baseline) / disparity_value; point.x = point.z * (x_pixels - cx) / focal_length; point.y = point.z * (y_pixels - cy) / focal_length; if (left_image.channels() == 3) { const cv::Vec3b& color = left_image.at<cv::Vec3b>(y_pixels, x_pixels); point.b = color[0]; point.g = color[1]; point.r = color[2]; } else if (left_image.channels() == 4) { const cv::Vec4b& color = left_image.at<cv::Vec4b>(y_pixels, x_pixels); point.b = color[0]; point.g = color[1]; point.r = color[2]; } else { point.b = left_image.at<uint8_t>(y_pixels, x_pixels); point.g = point.b; point.r = point.b; } if (freespace) { freespace_pointcloud->push_back(point); } else { pointcloud->push_back(point); } } } }
bool QrExtractor::extract( const cv::Mat & img ) { if ( pd->debug ) pd->orig = img.clone(); cv::cvtColor( img, pd->gray, CV_RGB2GRAY ); if ( pd->smoothSz > 0 ) { // Median accepts only odd values. cv::medianBlur( pd->gray, pd->blurred, (pd->smoothSz & 1) ? pd->smoothSz: pd->smoothSz+1 ); cv::blur( pd->blurred, pd->blurred, cv::Size( pd->smoothSz, pd->smoothSz ) ); } else pd->blurred = pd->gray; if ( !(pd->tresholdWndSz & 1) ) pd->tresholdWndSz |= 1; cv::adaptiveThreshold( pd->blurred, pd->blurred, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, pd->tresholdWndSz, 0.0 ); pd->blurredSaved = pd->blurred.clone(); cv::findContours( pd->blurred, pd->contours, pd->hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); //if ( pd->debug ) //{ // for( unsigned i = 0; i<pd->contours.size(); i++ ) // { // // Random color. // Scalar color = Scalar( pd->rng.uniform(0, 255), pd->rng.uniform(0,255), pd->rng.uniform(0,255) ); // // Draw contour function. // drawContours( pd->orig, pd->contours, i, color, 1, 8, pd->hierarchy, 0, Point() ); // } //} // Look for patterns. // There should be 3 squares. And each is a "pyramid of 3 squares" in turn. const double s1_s2_min = 1.0; //4.0/3.0; const double s1_s2_max = 6.0; //6.0/3.0; const double s2_s3_min = 1.0; //5.0/3.0; const double s2_s3_max = 6.0; //2.0/3.0; vector<Point> & markers = pd->markers; markers.clear(); for ( unsigned s3Ind=0; s3Ind<pd->hierarchy.size(); s3Ind++ ) { const Vec4i s3 = pd->hierarchy[s3Ind]; // If there is parent; if (s3[3] < 0) continue; const unsigned s2Ind = s3[3]; const Vec4i s2 = pd->hierarchy[ s2Ind ]; // If there is parent; if (s2[3] < 0) continue; const unsigned s1Ind = s2[3]; const Vec4i s1 = pd->hierarchy[ s1Ind ]; // Compare areas. const double s3Area = contourArea( pd->contours[ s3Ind ] ); if ( s3Area < 1.0 ) continue; const double s2Area = contourArea( pd->contours[ s2Ind ] ); if ( s2Area < 1.0 ) continue; const double ratio2_3 = s2Area/s3Area; if ( ( ratio2_3 < s2_s3_min ) || ( ratio2_3 > s2_s3_max ) ) continue; const double s1Area = contourArea( pd->contours[ s1Ind ] ); const double ratio1_2 = s1Area/s2Area; if ( ( ratio1_2 < s1_s2_min ) || ( ratio1_2 > s1_s2_max ) ) continue; Moments mu; double x, y; mu = moments( pd->contours[ s1Ind ] ); x = mu.m10 / mu.m00; y = mu.m01 / mu.m00; mu = moments( pd->contours[ s2Ind ] ); x += mu.m10 / mu.m00; y += mu.m01 / mu.m00; mu = moments( pd->contours[ s3Ind ] ); x += mu.m10 / mu.m00; y += mu.m01 / mu.m00; x *= 0.333333333; y *= 0.333333333; markers.push_back( Point( static_cast<int>(x), static_cast<int>(y) ) ); if ( markers.size() > 2 ) break; } // Sort markers. // First one should be middle one. // Second - one along X axis. // And the last one along (-Y) axis. if ( markers.size() > 2 ) { int indO = PD::detectO( pd->blurredSaved, markers ); const Point & o = markers[ indO ]; int indX = (indO+1)%3; int indY = (indO+2)%3; const Point & x = markers[ indX ]; const Point & y = markers[ indY ]; bool leftRf = PD::detectXy( o, x, y ); if ( !leftRf ) { int t = indX; indX = indY; indY = t; } markers.push_back( markers[ indO ] ); markers.push_back( markers[ indX ] ); markers.push_back( markers[ indY ] ); markers[0] = markers[3]; markers[1] = markers[4]; markers[2] = markers[5]; markers.resize( 3 ); } if ( pd->debug && ( markers.size() > 2 ) ) { cv::line( pd->orig, markers[0], markers[1], Scalar( 0, 0, 255 ), 3 ); cv::line( pd->orig, markers[0], markers[2], Scalar( 0, 255, 0 ), 3 ); //cv::line( pd->orig, markers[2], markers[0], Scalar( 0, 0, 255 ), 3 ); } if ( pd->debug ) { cv::imshow( "QrExtractor::orig", pd->orig ); cv::imshow( "QrExtractor::filtered", pd->blurredSaved ); } bool found = (markers.size() > 2); return found; }
/* Perform one thinning iteration. param im Binary image with range */ void thinningIteration(cv::Mat& img, int iter) { CV_Assert(img.channels() == 1); CV_Assert(img.depth() != sizeof(uchar)); CV_Assert(img.rows > 3 && img.cols > 3); cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1); int nRows = img.rows; int nCols = img.cols; if (img.isContinuous()) { nCols *= nRows; nRows = 1; } int x, y; uchar *pAbove; uchar *pCurr; uchar *pBelow; uchar *nw, *no, *ne; // north (pAbove) uchar *we, *me, *ea; uchar *sw, *so, *se; // south (pBelow) uchar *pDst; // initialize row pointers pAbove = NULL; pCurr = img.ptr<uchar>(0); pBelow = img.ptr<uchar>(1); for (y = 1; y < img.rows-1; ++y) { // shift the rows up by one pAbove = pCurr; pCurr = pBelow; pBelow = img.ptr<uchar>(y+1); pDst = marker.ptr<uchar>(y); // initialize col pointers no = &(pAbove[0]); ne = &(pAbove[1]); me = &(pCurr[0]); ea = &(pCurr[1]); so = &(pBelow[0]); se = &(pBelow[1]); for (x = 1; x < img.cols-1; ++x) { // shift col pointers left by one (scan left to right) nw = no; no = ne; ne = &(pAbove[x+1]); we = me; me = ea; ea = &(pCurr[x+1]); sw = so; so = se; se = &(pBelow[x+1]); int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) + (*ea == 0 && *se == 1) + (*se == 0 && *so == 1) + (*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) + (*we == 0 && *nw == 1) + (*nw == 0 && *no == 1); int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw; int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we); int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we); if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0) pDst[x] = 1; } } img &= ~marker; }
/** @brief RGBのヒストグラムを計算する @param src ヒストグラムを計算する画像 */ void HIST::calcHistgram(cv::Mat &src) { if(src.data == NULL) return; // グラフのデータ間の距離 step = (double)ui.histgramRGB->width()/256; int count[256][3]; int max = 0; // 初期化 for (int i = 0; i < 256; i++) for (int c = 0; c < 3; c++) count[i][c] = 0; // RGBごとに輝度の個数を取得 for (int j = 0; j < src.cols; j++) for (int i = 0; i < src.rows; i++) for (int c = 0; c < 3; c++) count[src.data[i * src.step + j * src.elemSize() + c]][c]++; // 0と255はだいたい極端に多くなるので無視する for (int c = 0; c < 3; c++) count[0][c] = count[255][c] = 0; // スケーリング定数(一番多い輝度の個数)の取得 for (int i = 0; i < 256; i++) for (int c = 0; c < 3; c++) if(max < count[i][c]) max = count[i][c]; // スケーリング double histgram[256][3]; for (int i = 0; i < 256; i++) for (int c = 0; c < 3; c++) histgram[i][c] = (double)count[i][c] / max * 200; /** 簡易グラフ作成 **/ int gWidth = 256 * step; int gHeight = 200; // 格子画像 cv::Mat baseGraph(gHeight, gWidth, CV_8UC3, cv::Scalar(255, 255, 255)); // RGBごとのヒストグラム画像 cv::Mat rgbGraph[3] = { cv::Mat(gHeight, gWidth, CV_8UC3, cv::Scalar(255, 255, 255)), cv::Mat(gHeight, gWidth, CV_8UC3, cv::Scalar(255, 255, 255)), cv::Mat(gHeight, gWidth, CV_8UC3, cv::Scalar(255, 255, 255)) }; // 上記4つを乗算ブレンディングした最終的に描画する画像 cv::Mat graph(gHeight, gWidth, CV_8UC3, cv::Scalar(255, 255, 255)); // 横のメモリ for (int i = 0; i < 20; i++) if(!(i%4)) cv::line(baseGraph, cv::Point(0, i*10), cv::Point(gWidth, i*10), cv::Scalar(180, 180, 180), 2); else cv::line(baseGraph, cv::Point(0, i*10), cv::Point(gWidth, i*10), cv::Scalar(200, 200, 200), 1); // 縦のメモリ for (int i = 0; i < 5; i++) cv::line(baseGraph, cv::Point(i*50*step, 0), cv::Point(i*50*step, gHeight), cv::Scalar(180, 180, 180), 2); // RGBごとのグラフ for (int i = 0; i < 256; i++){ cv::line(rgbGraph[0], cv::Point(i*step, 0), cv::Point(i*step, (int)histgram[i][0]), cv::Scalar(255, 200, 200), 2); cv::line(rgbGraph[1], cv::Point(i*step, 0), cv::Point(i*step, (int)histgram[i][1]), cv::Scalar(200, 255, 200), 2); cv::line(rgbGraph[2], cv::Point(i*step, 0), cv::Point(i*step, (int)histgram[i][2]), cv::Scalar(200, 200, 255), 2); } // 折れ線 for (int i = 0; i < 255; i++){ cv::line(rgbGraph[0], cv::Point(i*step, (int)histgram[i][0]), cv::Point((i+1)*step, (int)histgram[i+1][0]), cv::Scalar(255, 30, 30), 2, CV_AA); cv::line(rgbGraph[1], cv::Point(i*step, (int)histgram[i][1]), cv::Point((i+1)*step, (int)histgram[i+1][1]), cv::Scalar(30, 255, 30), 2, CV_AA); cv::line(rgbGraph[2], cv::Point(i*step, (int)histgram[i][2]), cv::Point((i+1)*step, (int)histgram[i+1][2]), cv::Scalar(30, 30, 255), 2, CV_AA); } // 合成 cv::Mat tmp; blend(rgbGraph[0], rgbGraph[1], tmp, blendType::MULTI); blend(tmp, rgbGraph[2], tmp, blendType::MULTI); blend(baseGraph, tmp, graph, blendType::MULTI); // 上下を反転 cv::flip(graph, graph, 0); drawForQtLabel(graph, ui.histgramRGB, false); }
float pixkit::qualityassessment::MSSIM(const cv::Mat &src1, const cv::Mat &src2, int HVSsize, double* lu_co_st) { ////////////////////////////////////////////////////////////////////////// // exception if(src1.empty()||src2.empty()){ CV_Error(CV_HeaderIsNull,"[qualityassessment::MSSIM] image is empty"); } if(src1.cols != src2.cols || src1.rows != src2.rows){ CV_Error(CV_StsBadArg,"[qualityassessment::MSSIM] sizes of two images are not equal"); } if(src1.type()!=CV_8U || src2.type()!=CV_8U){ CV_Error(CV_BadNumChannels,"[qualityassessment::MSSIM] image should be grayscale"); } ////////////////////////////////////////////////////////////////////////// const int L =255; double C1 = (0.01*L)*(0.01*L); //C1 = (K1*L)^2, K1=0.01, L=255(for 8-bit grayscale) double C2 = (0.03*L)*(0.03*L); //C1 = (K2*L)^2, K2=0.03, L=255(for 8-bit grayscale) double C3 = C2 / 2.0; int HalfSize = static_cast<int>(HVSsize/2); // gaussian filter /////////////////////////////////////////////////// // HVS filter std::vector< std::vector<double> > gaussianFilter( HVSsize, std::vector<double>(HVSsize) ); double sum = 0, STD = 1.5 ; for (int i=-HalfSize; i<=HalfSize; i++){ for (int j=-HalfSize; j<=HalfSize; j++){ gaussianFilter[i+HalfSize][j+HalfSize] = exp( -1 * (i*i+j*j) / (2*STD*STD) ); sum += gaussianFilter[i+HalfSize][j+HalfSize]; } } // Normalize to 0~1 for (int i=-HalfSize; i<=HalfSize; i++){ for (int j=-HalfSize; j<=HalfSize; j++){ gaussianFilter[i+HalfSize][j+HalfSize] /= sum; } } ///////////////////////////////////////////////////// double luminance=0, contrast=0, structure=0, SSIMresult = 0; for (int i=0; i<src1.rows; i++){ for (int j=0; j<src1.cols; j++){ double mean_x = 0, mean_y = 0, STDx = 0, STDy = 0, variance_xy = 0; // mean for (int x=-HalfSize; x<=HalfSize; x++){ for (int y=-HalfSize; y<=HalfSize; y++){ if (i+x<0 || j+y<0 || i+x>=src1.rows || j+y>=src1.cols){ continue; } else{ mean_x += src1.data[(i+x)*src1.cols + (j+y)] * gaussianFilter[x+HalfSize][y+HalfSize]; mean_y += src2.data[(i+x)*src2.cols + (j+y)] * gaussianFilter[x+HalfSize][y+HalfSize]; } } } // STD for (int x=-HalfSize; x<=HalfSize; x++){ for (int y=-HalfSize; y<=HalfSize; y++){ if (i+x<0 || j+y<0 || i+x>=src1.rows || j+y>=src1.cols){ continue; } else{ STDx += ((src1.data[(i+x)*src1.cols + (j+y)] - mean_x) * (src1.data[(i+x)*src1.cols + (j+y)] - mean_x) * gaussianFilter[x+HalfSize][y+HalfSize]); STDy += ((src2.data[(i+x)*src2.cols + (j+y)] - mean_y) * (src2.data[(i+x)*src2.cols + (j+y)] - mean_y) * gaussianFilter[x+HalfSize][y+HalfSize]); variance_xy += ((src1.data[(i+x)*src1.cols + (j+y)] - mean_x) * (src2.data[(i+x)*src2.cols + (j+y)] - mean_y) * gaussianFilter[x+HalfSize][y+HalfSize]); } } } STDx = sqrt(STDx); STDy = sqrt(STDy); SSIMresult += ((2*mean_x*mean_y + C1) * (2*variance_xy + C2)) / ((mean_x*mean_x + mean_y*mean_y + C1) * (STDx*STDx + STDy*STDy + C2)); // for MS_SSIM calculation if (lu_co_st != NULL){ luminance += (2*mean_x*mean_y + C1) / (mean_x*mean_x + mean_y*mean_y + C1); contrast += (2*STDx*STDy + C2) / (STDx*STDx + STDy*STDy + C2); structure += (variance_xy + C3) / (STDx*STDy + C3); } } } // for MS_SSIM calculation if (lu_co_st != NULL){ lu_co_st[0] = luminance / (src1.rows * src1.cols); lu_co_st[1] = contrast / (src1.rows * src1.cols); lu_co_st[2] = structure / (src1.rows * src1.cols); } SSIMresult /= (src1.rows * src1.cols); return SSIMresult; }
bool ParallaxErrorAnalysis_colorDiffPixels(const cv::Mat& img1,const shape& img1_shp, const cv::Mat& img2, const shape& img2_shp, const cv::Mat& img2_original, const cv::Mat& H, const cv::Size2i& img_size ,double& res_error) { vector<cv::Point2f> overlap_points; for(int r = 0 ; r < img_size.height; r++) { for(int c = 0; c < img_size.width; c++) { shape t_img1_shape = img1_shp; shape t_img2_shape = img2_shp; cv::Point2f t_point(c, r); if(t_img1_shape.isInShape(c, r) && t_img2_shape.isInShape(c, r) ) { // 记下这些点 overlap_points.push_back(t_point); } } } // 找到这些点在 img2_original 上的对应点 cv::Mat Hn = H.inv(); vector<cv::Point2f> correPoints_ori(overlap_points.size(),*new cv::Point2f); cv::perspectiveTransform(overlap_points, correPoints_ori, Hn); // 两个参数都要是 vector<cv::Point2f> f 不能是 i //检测有没有越界的 /*ofstream Dout("2.txt",ios::out); for(int i = 0; i < correPoints_ori.size(); i++) { if(correPoints_ori[i].x < 0 || correPoints_ori[i].x > img2_original.cols || correPoints_ori[i].y < 0 || correPoints_ori[i].y > img2_original.rows) { Dout<< correPoints_ori[i].x << " "<<correPoints_ori[i].y << endl; } } Dout.clear(); Dout.close();*/ // 计算 error res_error = 0; cv::Mat img_blend; vector<cv::Mat> imgs; vector<shape> shapes; imgs.push_back(img1); imgs.push_back(img2); shapes.push_back(img1_shp); shapes.push_back(img2_shp); blending_all(imgs, shapes, img_size, img_blend); double res = 0; double Be = 0, Ge = 0, Re = 0; for(int i = 0; i < overlap_points.size(); i++) { Be += abs( img_blend.at<Vec3b>(overlap_points[i])[0] - img2_original.at<Vec3b>(correPoints_ori[i])[0]); Ge += abs( img_blend.at<Vec3b>(overlap_points[i])[1] - img2_original.at<Vec3b>(correPoints_ori[i])[1]); Re += abs( img_blend.at<Vec3b>(overlap_points[i])[2] - img2_original.at<Vec3b>(correPoints_ori[i])[2]); } res = Be + Ge + Re; res_error = res; return true; }
float pixkit::qualityassessment::EME(const cv::Mat &src,const cv::Size nBlocks,const short mode){ ////////////////////////////////////////////////////////////////////////// // exceptions if(src.type()!=CV_8U){ CV_Assert(false); } if(nBlocks.width>src.cols||nBlocks.height>src.rows){ CV_Assert(false); } if(mode!=1&&mode!=2){ CV_Assert(false); } ////////////////////////////////////////////////////////////////////////// // param const float c = 0.0001; ////////////////////////////////////////////////////////////////////////// // define the stepsize float tempv1 = (float)src.cols/nBlocks.width, tempv2 = (float)src.rows/nBlocks.height; if((int)tempv1!=tempv1){ tempv1 = (int) tempv1+1.; } if((int)tempv2!=tempv2){ tempv2 = (int) tempv2+1.; } cv::Size stepsize((int)tempv1,(int)tempv2); ////////////////////////////////////////////////////////////////////////// // estimate int count = 0; float eme = 0.; for(int i=0;i<src.rows;i+=stepsize.height){ for(int j=0;j<src.cols;j+=stepsize.width){ // get local max and min float local_maxv = src.data[i*src.cols+j], local_minv = src.data[i*src.cols+j]; if(mode==1){ // standard mode for(int m=0;m<stepsize.height;m++){ for(int n=0;n<stepsize.width;n++){ if(i+m>=0&&i+m<src.rows&&j+n>=0&&j+n<src.cols){ if(src.data[(i+m)*src.cols+(j+n)]>local_maxv){ local_maxv = src.data[(i+m)*src.cols+(j+n)]; } if(src.data[(i+m)*src.cols+(j+n)]<local_minv){ local_minv = src.data[(i+m)*src.cols+(j+n)]; } } } } }else if(mode==2){ // BTC's mode // find first moment and second moment double moment1=0.,moment2=0.; int count_mom=0; for(int m=0;m<stepsize.height;m++){ for(int n=0;n<stepsize.width;n++){ if(i+m>=0&&i+m<src.rows&&j+n>=0&&j+n<src.cols){ moment1+=src.data[(i+m)*src.cols+(j+n)]; moment2+=src.data[(i+m)*src.cols+(j+n)]*src.data[(i+m)*src.cols+(j+n)]; count_mom++; } } } moment1/=(double)count_mom; moment2/=(double)count_mom; // find variance double sd=sqrt(moment2-moment1*moment1); // find num of higher than moment1 int q=0; for(int m=0;m<stepsize.height;m++){ for(int n=0;n<stepsize.width;n++){ if(i+m>=0&&i+m<src.rows&&j+n>=0&&j+n<src.cols){ if(src.data[(i+m)*src.cols+(j+n)]>=moment1){ q++; } } } } int m_q=count_mom-q; local_minv=moment1-sd*sqrt((double)q/m_q), local_maxv=moment1+sd*sqrt((double)m_q/q); if(local_minv>255){ local_minv=255; } if(local_minv<0){ local_minv=0; } if(local_maxv>255){ local_maxv=255; } if(local_maxv<0){ local_maxv=0; } }else{ assert(false); } // calc EME (Eq. 2) -totally same if(local_maxv!=local_minv){ eme += log((double)local_maxv/(local_minv+c)); } count++; } } return (float)20.*eme/count; }
int main(int argc, char* argv[]) { // welcome message std::cout<<"*********************************************************************************"<<std::endl; std::cout<<"* Retina demonstration for High Dynamic Range compression (tone-mapping) : demonstrates the use of a wrapper class of the Gipsa/Listic Labs retina model."<<std::endl; std::cout<<"* This retina model allows spatio-temporal image processing (applied on still images, video sequences)."<<std::endl; std::cout<<"* This demo focuses demonstration of the dynamic compression capabilities of the model"<<std::endl; std::cout<<"* => the main application is tone mapping of HDR images (i.e. see on a 8bit display a more than 8bits coded (up to 16bits) image with details in high and low luminance ranges"<<std::endl; std::cout<<"* The retina model still have the following properties:"<<std::endl; std::cout<<"* => It applies a spectral whithening (mid-frequency details enhancement)"<<std::endl; std::cout<<"* => high frequency spatio-temporal noise reduction"<<std::endl; std::cout<<"* => low frequency luminance to be reduced (luminance range compression)"<<std::endl; std::cout<<"* => local logarithmic luminance compression allows details to be enhanced in low light conditions\n"<<std::endl; std::cout<<"* for more information, reer to the following papers :"<<std::endl; std::cout<<"* Benoit A., Caplier A., Durette B., Herault, J., \"USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING\", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011"<<std::endl; std::cout<<"* Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891."<<std::endl; std::cout<<"* => reports comments/remarks at [email protected]"<<std::endl; std::cout<<"* => more informations and papers at : http://sites.google.com/site/benoitalexandrevision/"<<std::endl; std::cout<<"*********************************************************************************"<<std::endl; std::cout<<"** WARNING : this sample requires OpenCV to be configured with OpenEXR support **"<<std::endl; std::cout<<"*********************************************************************************"<<std::endl; std::cout<<"*** You can use free tools to generate OpenEXR images from images sets : ***"<<std::endl; std::cout<<"*** => 1. take a set of photos from the same viewpoint using bracketing ***"<<std::endl; std::cout<<"*** => 2. generate an OpenEXR image with tools like qtpfsgui.sourceforge.net ***"<<std::endl; std::cout<<"*** => 3. apply tone mapping with this program ***"<<std::endl; std::cout<<"*********************************************************************************"<<std::endl; // basic input arguments checking if (argc<2) { help("bad number of parameter"); return -1; } bool useLogSampling = !strcmp(argv[argc-1], "log"); // check if user wants retina log sampling processing std::string inputImageName=argv[1]; ////////////////////////////////////////////////////////////////////////////// // checking input media type (still image, video file, live video acquisition) std::cout<<"RetinaDemo: processing image "<<inputImageName<<std::endl; // image processing case // declare the retina input buffer... that will be fed differently in regard of the input media inputImage = cv::imread(inputImageName, -1); // load image in RGB mode std::cout<<"=> image size (h,w) = "<<inputImage.size().height<<", "<<inputImage.size().width<<std::endl; if (!inputImage.total()) { help("could not load image, program end"); return -1; } // rescale between 0 and 1 normalize(inputImage, inputImage, 0.0, 1.0, cv::NORM_MINMAX); cv::Mat gammaTransformedImage; cv::pow(inputImage, 1./5, gammaTransformedImage); // apply gamma curve: img = img ** (1./5) imshow("EXR image original image, 16bits=>8bits linear rescaling ", inputImage); imshow("EXR image with basic processing : 16bits=>8bits with gamma correction", gammaTransformedImage); if (inputImage.empty()) { help("Input image could not be loaded, aborting"); return -1; } ////////////////////////////////////////////////////////////////////////////// // Program start in a try/catch safety context (Retina may throw errors) try { /* create a retina instance with default parameters setup, uncomment the initialisation you wanna test * -> if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) */ if (useLogSampling) { retina = cv::createRetina(inputImage.size(),true, cv::RETINA_COLOR_BAYER, true, 2.0, 10.0); } else// -> else allocate "classical" retina : retina = cv::createRetina(inputImage.size()); // save default retina parameters file in order to let you see this and maybe modify it and reload using method "setup" retina->write("RetinaDefaultParameters.xml"); // desactivate Magnocellular pathway processing (motion information extraction) since it is not usefull here retina->activateMovingContoursProcessing(false); // declare retina output buffers cv::Mat retinaOutput_parvo; ///////////////////////////////////////////// // prepare displays and interactions histogramClippingValue=0; // default value... updated with interface slider //inputRescaleMat = inputImage; //outputRescaleMat = imageInputRescaled; cv::namedWindow("Retina input image (with cut edges histogram for basic pixels error avoidance)",1); cv::createTrackbar("histogram edges clipping limit", "Retina input image (with cut edges histogram for basic pixels error avoidance)",&histogramClippingValue,50,callBack_rescaleGrayLevelMat); cv::namedWindow("Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", 1); colorSaturationFactor=3; cv::createTrackbar("Color saturation", "Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", &colorSaturationFactor,5,callback_saturateColors); retinaHcellsGain=40; cv::createTrackbar("Hcells gain", "Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping",&retinaHcellsGain,100,callBack_updateRetinaParams); localAdaptation_photoreceptors=197; localAdaptation_Gcells=190; cv::createTrackbar("Ph sensitivity", "Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", &localAdaptation_photoreceptors,199,callBack_updateRetinaParams); cv::createTrackbar("Gcells sensitivity", "Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", &localAdaptation_Gcells,199,callBack_updateRetinaParams); ///////////////////////////////////////////// // apply default parameters of user interaction variables rescaleGrayLevelMat(inputImage, imageInputRescaled, (float)histogramClippingValue/100); retina->setColorSaturation(true,(float)colorSaturationFactor); callBack_updateRetinaParams(1,NULL); // first call for default parameters setup // processing loop with stop condition bool continueProcessing=true; while(continueProcessing) { // run retina filter retina->run(imageInputRescaled); // Retrieve and display retina output retina->getParvo(retinaOutput_parvo); cv::imshow("Retina input image (with cut edges histogram for basic pixels error avoidance)", imageInputRescaled/255.0); cv::imshow("Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", retinaOutput_parvo); cv::waitKey(10); } }catch(cv::Exception e) { std::cerr<<"Error using Retina : "<<e.what()<<std::endl; } // Program end message std::cout<<"Retina demo end"<<std::endl; return 0; }
cv::Mat Auvsi_Recognize::centerBinary( cv::Mat input ) { typedef cv::Vec<unsigned char, 1> VT_binary; cv::Mat buffered = cv::Mat( input.rows * 2, input.cols * 2, input.type() ); cv::Mat retVal; int centerX, centerY; int minX, minY, maxX, maxY; int radiusX, radiusY; std::vector<int> xCoords; std::vector<int> yCoords; // Get centroid cv::Moments imMoments = cv::moments( input, true ); centerX = (imMoments.m10 / imMoments.m00) - buffered.cols / 2; centerY = (imMoments.m01 / imMoments.m00) - buffered.rows / 2; // Get centered x and y coordinates cv::MatIterator_<VT_binary> inputIter = input.begin<VT_binary>(); cv::MatIterator_<VT_binary> inputEnd = input.end<VT_binary>(); for( ; inputIter != inputEnd; ++inputIter ) { unsigned char value = (*inputIter)[0]; if( value ) { xCoords.push_back( inputIter.pos().x - centerX ); yCoords.push_back( inputIter.pos().y - centerY ); } } if( xCoords.size() <= 0 || yCoords.size() <= 0 ) // nothing in image { return input; } // Get min and max x and y coords (centered) minX = *std::min_element( xCoords.begin(), xCoords.end() ); minY = *std::min_element( yCoords.begin(), yCoords.end() ); maxX = *std::max_element( xCoords.begin(), xCoords.end() ); maxY = *std::max_element( yCoords.begin(), yCoords.end() ); // Get new centroids centerX = getVectorMean<int>( xCoords ); centerY = getVectorMean<int>( yCoords ); // Get radius from center in each direction radiusX = std::max( abs(maxX - centerX), abs(centerX - minX) ); radiusY = std::max( abs(maxY - centerY), abs(centerY - minY) ); // Center image in temporary buffered array buffered = cvScalar(0); std::vector<int>::iterator iterX = xCoords.begin(); std::vector<int>::iterator endX = xCoords.end(); std::vector<int>::iterator iterY = yCoords.begin(); for( ; iterX != endX; ++iterX, ++iterY ) { buffered.at<VT_binary>( *iterY, *iterX ) = VT_binary(255); } // Center image buffered = buffered.colRange( centerX - radiusX, centerX + radiusX + 1 ); buffered = buffered.rowRange( centerY - radiusY, centerY + radiusY + 1 ); // Add extra padding to make square int outH, outW; outH = buffered.rows; outW = buffered.cols; if( outH < outW ) // pad height cv::copyMakeBorder( buffered, retVal, (outW-outH)/2, (outW-outH)/2, 0, 0, cv::BORDER_CONSTANT, cvScalar(0) ); else // pad width cv::copyMakeBorder( buffered, retVal, 0, 0, (outH-outW)/2, (outH-outW)/2, cv::BORDER_CONSTANT, cvScalar(0) ); // Make sure output is desired width cv::resize( retVal, buffered, input.size(), 0, 0, cv::INTER_NEAREST ); return buffered; }
void ControllerImageFusion::windowNormalization(cv::Mat &image, cv::Mat source) { float colRatioDb = image.cols/source.cols; float rowRatioDb = image.rows/source.rows; float val; if(std::modf(colRatioDb, &val)!= 0 || std::modf(rowRatioDb, &val) != 0) { return; } int colRatio = (int)(colRatioDb); int rowRatio = (int)(rowRatioDb); if(colRatio<=1 || rowRatio<=1) { return; } cv::Mat sourceConverted; source.convertTo(sourceConverted, CV_32F); int rows = image.rows; int cols = image.cols; for(int i = 0; i<=rows-rowRatio; i++) { for(int j = 0; j<=cols-colRatio; j++) { cv::Mat temp = cv::Mat(image, cv::Rect(j, i, colRatio, rowRatio)); cv::Scalar mean = cv::mean(temp); div_t rowDiv = std::div(i, rowRatio); div_t colDiv = std::div(j, colRatio); cv::Mat sourceTemp; // if we reached to the age do not go outside of the image int roiCols=2, roiRows=2; if(i==rows-rowRatio) { roiRows = 1; } if(j==cols-colRatio) { roiCols = 1; } cv::Mat sourceRoi = cv::Mat(sourceConverted, cv::Rect(colDiv.quot, rowDiv.quot, roiCols, roiRows)); sourceRoi.copyTo(sourceTemp); sourceTemp.at<float>(0, 0) = sourceTemp.at<float>(0, 0)*(colRatio-colDiv.rem)*(rowRatio-rowDiv.rem); if(roiRows>1) { sourceTemp.at<float>(1, 0) = sourceTemp.at<float>(1, 0)*(colRatio-colDiv.rem)*(rowDiv.rem); } if(roiCols>1) { sourceTemp.at<float>(0, 1) = sourceTemp.at<float>(0, 1)*(colDiv.rem)*(rowRatio-rowDiv.rem); } if(roiCols>1 && roiRows>1) { sourceTemp.at<float>(1, 1) = sourceTemp.at<float>(1, 1)*(colDiv.rem)*(rowDiv.rem); } sourceTemp = sourceTemp*(1.0/(rowRatio*colRatio)); cv::Scalar sourceMean = cv::sum(sourceTemp); mean.val[0] = sourceMean.val[0]-mean.val[0]; cv::add(temp, mean, temp); } } }
bool task3_5(const cv::Mat& image, const cv::Mat& orig) { cv::Mat grey, tmp, res; image.copyTo(grey); grey.convertTo(grey, CV_32F); grey.copyTo(res); res.convertTo(res, CV_8U); std::vector<cv::Mat> planes(2, cv::Mat()); std::vector<cv::Mat> polar(2, cv::Mat()); cv::dft(grey, tmp, cv::DFT_COMPLEX_OUTPUT); cv::split(tmp, planes); cv::cartToPolar(planes[0], planes[1], polar[0], polar[1]); int cx = polar[0].cols / 2; int cy = polar[0].rows / 2; cv::Point max; cv::Mat top = polar[0].rowRange(0, cx); cv::Mat bot = polar[0].rowRange(cx, polar[0].rows); int row = 0; do { cv::minMaxLoc(top.rowRange(row++, top.rows), 0, 0, 0, &max); } while (max.x == 0); int r = 3; cv::Mat noizeCol = polar[0].colRange(max.x - r, max.x + r); cv::Mat noizeRow = polar[0].rowRange(max.y - r, max.y + r); cv::Mat blurCol = polar[0].colRange(max.x - 12, max.x - 12 + 2 * r); cv::Mat blurRow = polar[0].rowRange(max.y - 3 * r, max.y - r); blurCol.copyTo(noizeCol); blurRow.copyTo(noizeRow); cv::Mat noizeColB = polar[0].colRange(polar[0].cols - max.x - r, polar[0].cols - max.x + r); cv::Mat noizeRowB = polar[0].rowRange(polar[0].rows - max.y - r, polar[0].rows - max.y + r); blurCol.copyTo(noizeColB); blurRow.copyTo(noizeRowB); cv::Mat roi = polar[0]; cv::Mat mean, stddev, tmp1; roi = roi.colRange(max.x + 20, roi.cols - max.x - 20).rowRange(max.y + 20, roi.cols - max.y - 20); for (int i = 0; i < roi.rows; ++i) { cv::Mat row = roi.row(i); cv::meanStdDev(row, mean, stddev); float m = mean.at<double>(0, 0); float st = stddev.at<double>(0, 0); for (Mfit mfit = row.begin<float>(); mfit != row.end<float>(); ++mfit) { if (*mfit > m + 1.5 * st) { *mfit = 0.5 * m; } } } visualization(polar[0], tmp); // // // cv::namedWindow("Lesson 2", CV_WINDOW_NORMAL); // cv::imshow("Lesson 2", tmp); // cv::waitKey(0); cv::polarToCart(polar[0], polar[1], planes[0], planes[1]); cv::merge(planes, tmp); cv::dft(tmp, tmp, cv::DFT_SCALE | cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT); tmp.convertTo(tmp, CV_8U); cv::Mat lut(1, 256, CV_32F, cv::Scalar(0)); for (int i = 0; i < 256; ++i) { lut.at<float>(0, i) = i; } for (int i = 65; i < 200; ++i) { lut.at<float>(0, i) = i - 30; } for (int i = 200; i < 220; ++i) { lut.at<float>(0, i) = i - 20; } lut.convertTo(lut, CV_8U); tmp.convertTo(tmp, CV_8U); cv::normalize(tmp, tmp, 0, 255, cv::NORM_MINMAX); cv::LUT(tmp, lut, tmp); cv::GaussianBlur(tmp, tmp, cv::Size(3, 3), 1); cv::medianBlur(tmp, tmp, 3); cv::Mat result; cv::matchTemplate(orig, tmp, result, CV_TM_SQDIFF); std::cout << "RMSE Task 3.5: " << result / (orig.cols * orig.rows) << std::endl; concatImages(res, tmp, res); cv::absdiff(tmp, orig, tmp); concatImages(res, tmp, res); cv::absdiff(image, orig, tmp); concatImages(res, tmp, res); concatImages(res, orig, res); // cv::namedWindow("Lesson 2", CV_WINDOW_NORMAL); // cv::imshow("Lesson 2", res); // cv::waitKey(0); return cv::imwrite(PATH + "Task3_5.jpg", res); }
vector<cv::Mat> UVDisparity::Pitch_Classify(cv::Mat &xyz,cv::Mat& ground_mask) { vector<cv::Mat> pitch_measure; cv::Mat pitch1; pitch1.create(1,1,CV_32F); cv::Mat pitch2; pitch2.create(1,1,CV_32F); cv::Mat bin,dst,dst1; GaussianBlur(v_dis_,dst,Size(3,3),0,0); Mat element = getStructuringElement(MORPH_RECT,Size(3,3),Point(1,1)); erode(dst,dst1,element); cv::threshold(dst1,bin,0,255,THRESH_OTSU); //cv::imshow("color",bin); //cv::waitKey(0); std::vector<Point> pt_list; //select the points to estimate line function for(int i = 26;i < bin.cols;i++) { for(int j = bin.rows-1;j>=0;j--) { int v = bin.at<uchar>(j,i); if(v == 255) { //cout<<"the lowest pixel is: "<<i<<","<<j<<endl; pt_list.push_back(cv::Point(i,j)); for(int k = j; k > max(j-30,0); k--) { int v_a = bin.at<uchar>(k,i); if(v_a == 255) { pt_list.push_back(cv::Point(i,k)); } } break; } } } std::vector<Point> pt_list2; //select the points to estimate line function for(int i = 12;i < 26;i++) { for(int j = bin.rows-1;j>=0;j--) { int v = bin.at<uchar>(j,i); if(v == 255) { pt_list2.push_back(cv::Point(i,j)); break; } } } //cout<<"length of list is: "<<pt_list.size()<<endl; Vec4f line1; Vec4f line2; //fitting line function cv::fitLine(pt_list,line1,CV_DIST_L2,0,0.01,0.01); cv::fitLine(pt_list,line2,CV_DIST_L2,0,0.01,0.01); //cv::fitLine(pt_list2,line2,CV_DIST_L2,0,0.01,0.01); float a = line1[0];float b = line1[1]; int x0 = cvRound(line1[2]);int y0 = cvRound(line1[3]); float a2 = line2[0];float b2 = line2[1]; int x2 = cvRound(line2[2]);int y2 = cvRound(line2[3]); double V_C = y0 - (b/a)*x0; double V_C2 = y2 - (b2/a2)*x2; vector<Vec4i> lines; double V_0 = calib_.c_y; double F = calib_.f; double theta = atan((V_0-V_C)/F); double theta2 = atan((V_0-V_C2)/F); cv::line(v_dis_show,cv::Point(0,(b2/a2)*0+V_C2),cv::Point(26,(b2/a2)*26+V_C2),cv::Scalar(0,255,0),2,8); cv::line(v_dis_show,cv::Point(0,(b2/a2)*0+V_C2-20),cv::Point(26,(b2/a2)*26+V_C2-20),cv::Scalar(0,0,255),2,8); cv::line(v_dis_show,cv::Point(26,(b/a)*26+V_C),cv::Point(100,(b/a)*100+V_C),cv::Scalar(255,0,0),2,8); cv::line(v_dis_show,cv::Point(26,(b/a)*26+V_C-20),cv::Point(100,(b/a)*100+V_C-20),cv::Scalar(0,0,255),2,8); pitch1.at<float>(0)=theta; pitch2.at<float>(0)=theta2; //classify the points on ground plane and obstacles with respect to its distance to the line in V-disparity int xyz_cols = xyz.cols; int xyz_rows = xyz.rows; for(int j = 0; j < xyz_rows; j++) { float* xyz_ptr = xyz.ptr<float>(j); for(int i = 0;i < xyz_cols; i++) { float v = xyz_ptr[10*i + 4]; float d = xyz_ptr[10*i + 5]; int intensity = cvRound(xyz_ptr[10*i + 6]); float distance = (v-(b/a)*d-V_C); if(d > 26.0f) { if(distance > -14.0f) { xyz_ptr[10*i+9] = 0.0f;//make the intensity as zero } else { xyz_ptr[10*i+9] = abs(intensity); } } else if(d < 26.1f && d > 8.0f) { if(distance > -14.0f) { xyz_ptr[10*i+9] = 0.0f;//make the intensity as zero } else { xyz_ptr[10*i+9] = abs(intensity); } } else { xyz_ptr[10*i+9] = 0;//make the intensity as zero } } } vector<Mat> channels(8); // split img: split(xyz, channels); // get the channels (dont forget they follow BGR order in OpenCV) cv::Mat ch9 = channels[9]; ground_mask.create(ch9.size(),CV_8UC1); cv::convertScaleAbs(ch9,ground_mask); pitch_measure.push_back(pitch1); pitch_measure.push_back(pitch2); return pitch_measure; }
void scaleImage(const cv::Mat& src, cv::Mat& dst, double alpha, double beta) { CV_Assert(src.channels() == 3); dst = alpha * src + cv::Scalar(beta, beta, beta); }
// //Write an image to the stream void ImageSequenceIO::WriteImageToStream(const cv::Mat &image, const int frameId) { m_pState->m_ofs.write((char*)&m_pState->m_readFrameId,sizeof(int)); m_pState->m_ofs.write((const char*)image.ptr(),m_pState->m_writeHeader.totalSize()); }
void CVThread::setImage(const cv::Mat& img) { m_frames.m_result = m_frames.m_inFrame = img.clone(); emit imageChanged(); }
void DataTransformer<Dtype>::Transform(const cv::Mat& cv_img, Blob<Dtype>* transformed_blob, bool preserve_pixel_vals) { const int img_channels = cv_img.channels(); const int img_height = cv_img.rows; const int img_width = cv_img.cols; // Check dimensions. const int channels = transformed_blob->channels(); const int height = transformed_blob->height(); const int width = transformed_blob->width(); const int num = transformed_blob->num(); CHECK_EQ(channels, img_channels); CHECK_LE(height, img_height); CHECK_LE(width, img_width); CHECK_GE(num, 1); CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte"; const int crop_size = param_.crop_size(); const Dtype scale = preserve_pixel_vals ? 1 : param_.scale(); const bool do_mirror = param_.mirror() && Rand(2); const bool has_mean_file = param_.has_mean_file(); const bool has_mean_values = mean_values_.size() > 0; CHECK_GT(img_channels, 0); CHECK_GE(img_height, crop_size); CHECK_GE(img_width, crop_size); Dtype* mean = NULL; if (has_mean_file && !preserve_pixel_vals) { CHECK_EQ(img_channels, data_mean_.channels()); CHECK_EQ(img_height, data_mean_.height()); CHECK_EQ(img_width, data_mean_.width()); mean = data_mean_.mutable_cpu_data(); } if (has_mean_values && !preserve_pixel_vals) { CHECK(mean_values_.size() == 1 || mean_values_.size() == img_channels) << "Specify either 1 mean_value or as many as channels: " << img_channels; if (img_channels > 1 && mean_values_.size() == 1) { // Replicate the mean_value for simplicity for (int c = 1; c < img_channels; ++c) { mean_values_.push_back(mean_values_[0]); } } } int h_off = 0; int w_off = 0; cv::Mat cv_cropped_img = cv_img; if (crop_size) { CHECK_EQ(crop_size, height); CHECK_EQ(crop_size, width); // We only do random crop when we do training. if (phase_ == TRAIN) { h_off = Rand(img_height - crop_size + 1); w_off = Rand(img_width - crop_size + 1); } else { h_off = (img_height - crop_size) / 2; w_off = (img_width - crop_size) / 2; } cv::Rect roi(w_off, h_off, crop_size, crop_size); cv_cropped_img = cv_img(roi); } else { CHECK_EQ(img_height, height); CHECK_EQ(img_width, width); } CHECK(cv_cropped_img.data); Dtype* transformed_data = transformed_blob->mutable_cpu_data(); int top_index; for (int h = 0; h < height; ++h) { const uchar* ptr = cv_cropped_img.ptr<uchar>(h); int img_index = 0; for (int w = 0; w < width; ++w) { for (int c = 0; c < img_channels; ++c) { if (do_mirror) { top_index = (c * height + h) * width + (width - 1 - w); } else { top_index = (c * height + h) * width + w; } // int top_index = (c * height + h) * width + w; Dtype pixel = static_cast<Dtype>(ptr[img_index++]); if (has_mean_file && !preserve_pixel_vals) { int mean_index = (c * img_height + h_off + h) * img_width + w_off + w; transformed_data[top_index] = (pixel - mean[mean_index]) * scale; } else { if (has_mean_values && !preserve_pixel_vals) { transformed_data[top_index] = (pixel - mean_values_[c]) * scale; } else { transformed_data[top_index] = pixel * scale; } } } } } }
void ScaleMaps::run(const cv::Mat& img, const vector<FeatureType>& features, vector<float>& scaleMap) { size_t r, c, i, j, nr, nc, min_row, max_row, min_col, max_col; size_t neighborCount, coefficientCount = 0; std::vector<Eigen::Triplet<float>> coefficients; // list of non-zeros coefficients vector<float> weights(9); float m, v, sum; size_t pixels = img.total(); int index = -1, nindex; // Initialization vector<bool> scale(pixels, false); for (i = 0; i < features.size(); ++i) { const FeatureType& feat = features[i]; scale[((int)feat.y)*img.cols + (int)feat.x] = true; } // Adjust image values cv::Mat scaledImg = img.clone(); scaledImg += 1; scaledImg *= (1 / 32.0f); // For each pixel in the image for (r = 0; r < scaledImg.rows; ++r) { min_row = (size_t)std::max(int(r - 1), 0); max_row = (size_t)std::min(scaledImg.rows - 1, int(r + 1)); for (c = 0; c < scaledImg.cols; ++c) { // Increment pixel index ++index; // If this is not a feature point if (!scale[index]) { min_col = (size_t)std::max(int(c - 1), 0); max_col = (size_t)std::min(scaledImg.cols - 1, int(c + 1)); neighborCount = 0; // Loop over 3x3 neighborhoods matrix // and calculate the variance of the intensities for (nr = min_row; nr <= max_row; ++nr) { for (nc = min_col; nc <= max_col; ++nc) { if (nr == r && nc == c) continue; weights[neighborCount++] = scaledImg.at<float>(nr, nc); } } weights[neighborCount] = scaledImg.at<float>(r, c); // Calculate the weights statistics getStat(weights, neighborCount + 1, m, v); m *= 0.6; if (v < EPS) v = EPS; // Avoid division by 0 // Apply weight function mWeightFunc(weights, neighborCount, scaledImg.at<float>(r, c), m, v); // Normalize the weights and set to coefficients sum = std::accumulate(weights.begin(), weights.begin() + neighborCount, 0.0f); i = 0; for (nr = min_row; nr <= max_row; ++nr) { for (nc = min_col; nc <= max_col; ++nc) { if (nr == r && nc == c) continue; nindex = nr*scaledImg.cols + nc; coefficients.push_back(Eigen::Triplet<float>( index, nindex, -weights[i++] / sum)); } } } // Add center coefficient coefficients.push_back(Eigen::Triplet<float>(index, index, 1)); } } // Build right side equation vector Eigen::VectorXf b = Eigen::VectorXf::Zero(pixels); for (i = 0; i < features.size(); ++i) { const FeatureType& feat = features[i]; b[((int)feat.y)*scaledImg.cols + (int)feat.x] = feat.scale; } // Build left side equation matrix Eigen::SparseMatrix<float> A(pixels, pixels); A.setFromTriplets(coefficients.begin(), coefficients.end()); /*/// Debug /// std::ofstream file("Output.m"); cv::Mat_<int> rows(1, coefficients.size()), cols(1, coefficients.size()); cv::Mat_<float> values(1, coefficients.size()); for (i = 0; i < coefficients.size(); ++i) { rows.at<int>(i) = coefficients[i].row(); cols.at<int>(i) = coefficients[i].col(); values.at<float>(i) = coefficients[i].value(); } file << "cpp_rows = " << rows << ";" << std::endl; file << "cpp_cols = " << cols << ";" << std::endl; file << "cpp_values = " << values << ";" << std::endl; /////////////*/ // Solving Eigen::SparseLU<Eigen::SparseMatrix<float>> slu(A); Eigen::VectorXf x = slu.solve(b); // Copy to output scaleMap.resize(pixels); memcpy(scaleMap.data(), x.data(), pixels*sizeof(float)); }