GuidedFilterMono::GuidedFilterMono(const cv::Mat &origI, int r, double eps) : r(r), eps(eps) { if (origI.depth() == CV_32F || origI.depth() == CV_64F) I = origI.clone(); else I = convertTo(origI, CV_32F); Idepth = I.depth(); mean_I = boxfilter(I, r); cv::Mat mean_II = boxfilter(I.mul(I), r); var_I = mean_II - mean_I.mul(mean_I); }
cv::Mat GuidedFilterMono::filterSingleChannel(const cv::Mat &p) const { cv::Mat mean_p = boxfilter(p, r); cv::Mat mean_Ip = boxfilter(I.mul(p), r); cv::Mat cov_Ip = mean_Ip - mean_I.mul(mean_p); // this is the covariance of (I, p) in each local patch. cv::Mat a = cov_Ip / (var_I + eps); // Eqn. (5) in the paper; cv::Mat b = mean_p - a.mul(mean_I); // Eqn. (6) in the paper; cv::Mat mean_a = boxfilter(a, r); cv::Mat mean_b = boxfilter(b, r); return mean_a.mul(I) + mean_b; }
GuidedFilterColor::GuidedFilterColor(const cv::Mat &origI, int r, double eps) : r(r), eps(eps) { cv::Mat I; if (origI.depth() == CV_32F || origI.depth() == CV_64F) I = origI.clone(); else I = convertTo(origI, CV_32F); Idepth = I.depth(); cv::split(I, Ichannels); mean_I_r = boxfilter(Ichannels[0], r); mean_I_g = boxfilter(Ichannels[1], r); mean_I_b = boxfilter(Ichannels[2], r); // variance of I in each local patch: the matrix Sigma in Eqn (14). // Note the variance in each local patch is a 3x3 symmetric matrix: // rr, rg, rb // Sigma = rg, gg, gb // rb, gb, bb cv::Mat var_I_rr = boxfilter(Ichannels[0].mul(Ichannels[0]), r) - mean_I_r.mul(mean_I_r) + eps; cv::Mat var_I_rg = boxfilter(Ichannels[0].mul(Ichannels[1]), r) - mean_I_r.mul(mean_I_g); cv::Mat var_I_rb = boxfilter(Ichannels[0].mul(Ichannels[2]), r) - mean_I_r.mul(mean_I_b); cv::Mat var_I_gg = boxfilter(Ichannels[1].mul(Ichannels[1]), r) - mean_I_g.mul(mean_I_g) + eps; cv::Mat var_I_gb = boxfilter(Ichannels[1].mul(Ichannels[2]), r) - mean_I_g.mul(mean_I_b); cv::Mat var_I_bb = boxfilter(Ichannels[2].mul(Ichannels[2]), r) - mean_I_b.mul(mean_I_b) + eps; // Inverse of Sigma + eps * I invrr = var_I_gg.mul(var_I_bb) - var_I_gb.mul(var_I_gb); invrg = var_I_gb.mul(var_I_rb) - var_I_rg.mul(var_I_bb); invrb = var_I_rg.mul(var_I_gb) - var_I_gg.mul(var_I_rb); invgg = var_I_rr.mul(var_I_bb) - var_I_rb.mul(var_I_rb); invgb = var_I_rb.mul(var_I_rg) - var_I_rr.mul(var_I_gb); invbb = var_I_rr.mul(var_I_gg) - var_I_rg.mul(var_I_rg); cv::Mat covDet = invrr.mul(var_I_rr) + invrg.mul(var_I_rg) + invrb.mul(var_I_rb); invrr /= covDet; invrg /= covDet; invrb /= covDet; invgg /= covDet; invgb /= covDet; invbb /= covDet; }
cv::Mat GuidedFilterColor::filterSingleChannel(const cv::Mat &p) const { cv::Mat mean_p = boxfilter(p, r); cv::Mat mean_Ip_r = boxfilter(Ichannels[0].mul(p), r); cv::Mat mean_Ip_g = boxfilter(Ichannels[1].mul(p), r); cv::Mat mean_Ip_b = boxfilter(Ichannels[2].mul(p), r); // covariance of (I, p) in each local patch. cv::Mat cov_Ip_r = mean_Ip_r - mean_I_r.mul(mean_p); cv::Mat cov_Ip_g = mean_Ip_g - mean_I_g.mul(mean_p); cv::Mat cov_Ip_b = mean_Ip_b - mean_I_b.mul(mean_p); cv::Mat a_r = invrr.mul(cov_Ip_r) + invrg.mul(cov_Ip_g) + invrb.mul(cov_Ip_b); cv::Mat a_g = invrg.mul(cov_Ip_r) + invgg.mul(cov_Ip_g) + invgb.mul(cov_Ip_b); cv::Mat a_b = invrb.mul(cov_Ip_r) + invgb.mul(cov_Ip_g) + invbb.mul(cov_Ip_b); cv::Mat b = mean_p - a_r.mul(mean_I_r) - a_g.mul(mean_I_g) - a_b.mul(mean_I_b); // Eqn. (15) in the paper; return (boxfilter(a_r, r).mul(Ichannels[0]) + boxfilter(a_g, r).mul(Ichannels[1]) + boxfilter(a_b, r).mul(Ichannels[2]) + boxfilter(b, r)); // Eqn. (16) in the paper; }
int main (int argc, char** argv) { // Open a webcamera cv::VideoCapture camera(0); cv::Mat frame; if(!camera.isOpened()) return -1; camera.set(CV_CAP_PROP_FRAME_WIDTH, 640); camera.set(CV_CAP_PROP_FRAME_HEIGHT, 480); camera >> frame; // create CPU/GPU shared images - one for the initial and one for the result cv::Mat sGray(frame.size(), CV_8U, createImageBuffer(frame.size().width * frame.size().height)); cv::Mat dGray(frame.size(), CV_8U, createImageBuffer(frame.size().width * frame.size().height)); cv::Mat eGray(frame.size(), CV_8U, createImageBuffer(frame.size().width * frame.size().height)); cv::cvtColor(frame, dGray, CV_BGR2GRAY); cv::cvtColor(frame, eGray, CV_BGR2GRAY); // Create the capture windows cv::namedWindow("Source"); cv::namedWindow("Greyscale"); cv::namedWindow("Blurred"); cv::namedWindow("Sobel"); // Loop while capturing images while(1) { // Capture the image and store a gray conversion for the gpu camera >> frame; cv::cvtColor(frame, sGray, CV_BGR2GRAY); // Perform the gpu based blur struct timeval tv; struct timezone tz; struct tm *tm; gettimeofday(&tv, &tz); tm=localtime(&tv.tv_sec); printf(" %d:%02d:%02d %d \n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec); boxfilter(frame.size().width, frame.size().height, sGray.data, dGray.data, 3, 3); sobelfilter(frame.size().width, frame.size().height, dGray.data, eGray.data); gettimeofday(&tv, &tz); tm=localtime(&tv.tv_sec); printf(" %d:%02d:%02d %d \n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec); // Show the results cv::imshow("Source", frame); cv::imshow("Greyscale", sGray); cv::imshow("Blurred", dGray); cv::imshow("Sobel", eGray); } // Exit destroyImageBuffer(sGray.data); destroyImageBuffer(dGray.data); destroyImageBuffer(eGray.data); return 0; }