/* * Class: com_cabatuan_mysuperpixels_MainActivity * Method: filter * Signature: (Landroid/graphics/Bitmap;[B)V */ JNIEXPORT void JNICALL Java_com_cabatuan_mysuperpixels_MainActivity_process (JNIEnv *pEnv, jobject clazz, jobject pTarget, jbyteArray pSource, jint compactness){ AndroidBitmapInfo bitmapInfo; uint32_t* bitmapContent; // Links to Bitmap content if(AndroidBitmap_getInfo(pEnv, pTarget, &bitmapInfo) < 0) abort(); if(bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) abort(); if(AndroidBitmap_lockPixels(pEnv, pTarget, (void**)&bitmapContent) < 0) abort(); /// Access source array data... OK jbyte* source = (jbyte*)pEnv->GetPrimitiveArrayCritical(pSource, 0); if (source == NULL) abort(); Mat src(bitmapInfo.height + bitmapInfo.height/2, bitmapInfo.width, CV_8UC1, (unsigned char *)source); Mat mbgra(bitmapInfo.height, bitmapInfo.width, CV_8UC4, (unsigned char *)bitmapContent); /***********************************************************************************************/ //outputGray(src.rowRange(0, bitmapInfo.height), bitmapContent); if (tempBGR.empty()) tempBGR.create(bitmapInfo.height/2, bitmapInfo.width/2, CV_8UC3); //extractYUV(src, tempBGRA); extractVU_method3(src, tempBGR); // YUV extraction OK // Reduce color colorReduction(tempBGR, tempBGR, 4); s.generateSuperpixels(tempBGR, compactness); cv::Mat BGRscaled; cv::resize(tempBGR, BGRscaled, mbgra.size()); //s.displayCenters(BGRscaled, cv::Scalar( 0, 255, 0)); // OK s.displayContours(BGRscaled); cv::cvtColor(BGRscaled, mbgra, CV_BGR2BGRA); /***********************************************************************************************/ // Sanity check: okay! //cvtColor(src.rowRange(0, bitmapInfo.height), mbgra, CV_GRAY2BGRA); /************************************************************************************************/ /// Release Java byte buffer and unlock backing bitmap pEnv-> ReleasePrimitiveArrayCritical(pSource,source,0); if (AndroidBitmap_unlockPixels(pEnv, pTarget) < 0) abort(); }
float ExplainedVariationNormal(const Superpixels& sp) { Eigen::Vector3f mean_normal = Eigen::Vector3f::Zero(); unsigned int num_valid = 0; for(const Point& p : sp.points) { if(p.is_valid) { mean_normal += p.normal; num_valid++; } } mean_normal /= mean_normal.norm(); // auto part = sp.ComputePartition(); // std::cout << mean_normal.transpose() << std::endl; // for(unsigned int i=0; i<part.numSegments(); i++) { // std::cout << mean_normal.transpose() << std::endl; // std::cout << sp.cluster[i].center.normal.transpose() << " -> " << 1.0f - mean_normal.dot(sp.cluster[i].center.normal.transpose()) << std::endl; // float total = 0.0f; // for(unsigned int j : part.segmentPixelIds(i)) { // float d = 1.0f - mean_normal.dot(sp.points[j].normal); // total += d; // std::cout << "\t" << sp.points[j].normal.transpose() << " -> " << d << std::endl; // } // total /= static_cast<float>(part.segmentSize(i)); // std::cout << "total=" << total << std::endl; // } return ExplainedVariation( sp.ComputePartition(), [&sp](unsigned int j) { return sp.points[j].normal; }, [&sp](unsigned int i) { return sp.cluster[i].center.normal; }, mean_normal, [](const Eigen::Vector3f& a, const Eigen::Vector3f& b) { return 1.0f - a.dot(b); } ); }
std::vector<std::vector<BorderPixel>> ComputeBorderLabels(const Superpixels& spc) { slimage::Image1i labels = spc.ComputeLabels(); std::vector<std::vector<BorderPixel>> border_pixels(spc.cluster.size()); for(unsigned int cid=0; cid<spc.cluster.size(); cid++) { border_pixels[cid] = ComputeBorderLabels(cid, spc, labels); } return border_pixels; }
float CompressionErrorPosition(const Superpixels& sp) { return CompressionError( sp.ComputePartition(), [&sp](unsigned int j) { return sp.points[j].position; }, [&sp](unsigned int i) { return sp.cluster[i].center.position; }, [](const Eigen::Vector3f& a, const Eigen::Vector3f& b) { return (a-b).norm(); } ); }
float CompressionErrorDepth(const Superpixels& sp) { return CompressionError( sp.ComputePartition(), [&sp](unsigned int j) { return sp.points[j].depth(); }, [&sp](unsigned int i) { return sp.cluster[i].center.depth(); }, [](float a, float b) { return std::abs(a-b); } ); }
NeighbourhoodGraph CreateNeighborhoodGraph(const Superpixels& superpixels, NeighborGraphSettings settings) { // create one node for each superpixel NeighbourhoodGraph neighbourhood_graph(superpixels.clusterCount()); // compute superpixel borders std::vector<std::vector<BorderPixel> > border = ComputeBorderLabels(superpixels); // connect superpixels const float spatial_distance_threshold = settings.spatial_distance_mult_threshold * superpixels.opt.base_radius; const float pixel_distance_mult_threshold = settings.pixel_distance_mult_threshold; for(unsigned int i=0; i<superpixels.cluster.size(); i++) { for(unsigned int j=i+1; j<superpixels.cluster.size(); j++) { const Point& c_i = superpixels.cluster[i].center; const Point& c_j = superpixels.cluster[j].center; // early test if the two superpixels are even near to each other if(settings.cut_by_spatial) { // spatial distance float d = (c_i.position - c_j.position).norm(); // only test if distance is smaller than threshold if(d > spatial_distance_threshold) { continue; } } else { // pixel distance on camera image plane float d = std::sqrt(static_cast<float>(metric::PixelDistanceSquared(c_i,c_j))); // only test if pixel distance is smaller then C * pixel_radius float r = std::max(c_i.cluster_radius_px, c_j.cluster_radius_px); if(d > pixel_distance_mult_threshold * r) { continue; } } // compute intersection of border pixels std::vector<unsigned int> common_border = FindCommonBorder(border, i, j); // test if superpixels have a common border unsigned int common_border_size = common_border.size(); if(common_border_size < settings.min_abs_border_overlap) { continue; } float p = static_cast<float>(common_border_size) / static_cast<float>(std::min(border[i].size(), border[j].size())); if(p < settings.min_border_overlap) { continue; } // add edge NeighbourhoodGraph::edge_descriptor eid; bool ok; boost::tie(eid,ok) = boost::add_edge(i, j, neighbourhood_graph); // FIXME correctly convert superpixel_id to vertex descriptor assert(ok); neighbourhood_graph[eid].num_border_pixels = common_border_size; neighbourhood_graph[eid].border_pixel_ids = common_border; } } return neighbourhood_graph; }
float CompressionErrorNormal(const Superpixels& sp) { return CompressionError( sp.ComputePartition(), [&sp](unsigned int j) { return sp.points[j].normal; }, [&sp](unsigned int i) { return sp.cluster[i].center.normal; }, [](const Eigen::Vector3f& a, const Eigen::Vector3f& b) { // protect acos from slightly wrong dot product results float h = a.dot(b); h = std::min(1.0f, std::max(0.0f, h)); return 180.0f / boost::math::constants::pi<float>() * std::acos(h); } ); }
std::vector<unsigned int> ComputeAllBorderPixels(const Superpixels& superpixels) { slimage::Image1i labels = superpixels.ComputeLabels(); std::set<unsigned int> u; int face_neighbours[] = { -1, +1, -static_cast<int>(labels.width()), static_cast<int>(labels.width()) }; for(unsigned int y=1; y<labels.height()-1; y++) { for(unsigned int x=1; x<labels.width()-1; x++) { int q = labels.index(x,y); unsigned int lc = labels[q]; for(unsigned int i=0; i<4; i++) { if(labels[q + face_neighbours[i]] != lc) { u.insert(q); } } } } return std::vector<unsigned int>(u.begin(), u.end()); }
float ExplainedVariationPosition(const Superpixels& sp) { Eigen::Vector3f mean_pos = Eigen::Vector3f::Zero(); unsigned int num_valid = 0; for(const Point& p : sp.points) { if(p.is_valid) { mean_pos += p.position; num_valid++; } } mean_pos /= static_cast<float>(num_valid); return ExplainedVariation( sp.ComputePartition(), [&sp](unsigned int j) { return sp.points[j].position; }, [&sp](unsigned int i) { return sp.cluster[i].center.position; }, mean_pos, [](const Eigen::Vector3f& a, const Eigen::Vector3f& b) { return (a-b).norm(); } ); }
float ExplainedVariationDepth(const Superpixels& sp) { float mean_depth = 0.0f; unsigned int num_valid = 0; for(const Point& p : sp.points) { if(p.is_valid) { mean_depth += p.depth(); num_valid++; } } mean_depth /= static_cast<float>(num_valid); return ExplainedVariation( sp.ComputePartition(), [&sp](unsigned int j) { return sp.points[j].depth(); }, [&sp](unsigned int i) { return sp.cluster[i].center.depth(); }, mean_depth, [](float a, float b) { return std::abs(a-b); } ); }
// ./Sp_demo_for_direc.py -d <directory_name> -i_std ... -n... --imgs_of_the_same_size int main( int argc, char** argv ) { // get the image filename, nPixels_in_square_side and i_std // the defaults const char* direc = "image/"; int nPixels_in_square_side = 15; int i_std = 20; bool same_size = false; for (int i = 1; i < argc; ++i) { std::string arg = argv[i]; if ((arg == "-h") || (arg == "--help")) { show_usage(argv[0]); return 0; } else if ((arg == "-d") || (arg == "--image_direc")) { if (i + 1 < argc) { i++; direc = argv[i]; } else { std::cerr << "--img_filename option requires one argument." << std::endl; return 1; } } else if ((arg == "-n") || (arg == "--nPixels_on_side")) { if (i + 1 < argc) { i++; nPixels_in_square_side = atoi (argv[i]); if (nPixels_in_square_side<3) { std::cerr << "--nPixels_in_square_side option requires nPixels_in_square_side >= 3." << std::endl; return 1; } } else { std::cerr << "--nPixels_on_side option requires one argument." << std::endl; return 1; } } else if (arg == "--i_std") { if (i + 1 < argc) { i++; i_std = atoi (argv[i]); if (i_std<5 || i_std>40) { std::cerr << "--i_std option requires 5<= value <=40." << std::endl; return 1; } } else { std::cerr << "--i_std option requires a number." << std::endl; return 1; } }else{ } } DIR *dpdf; struct dirent *epdf; superpixel_options spoptions = get_sp_options(nPixels_in_square_side,i_std); int count = 0; //Superpixels sp = Superpixels(0,0,spoptions); dpdf = opendir(direc); if (dpdf != NULL){ while (epdf = readdir(dpdf)){ String img_name = epdf->d_name; String filename = string(direc) + img_name; Mat image = imread(filename, CV_LOAD_IMAGE_COLOR); if(! image.data )continue; cout << "Filename: " << filename <<endl; Superpixels sp = Superpixels(image.cols, image.rows, spoptions); cudaDeviceSynchronize(); //cout << "finish init sp" << endl; sp.load_img((unsigned char*)(image.data)); //cout << "finish loading the image" << endl; // Part 3: Do the superpixel segmentation clock_t start,finish; start = clock(); sp.calc_seg(); cudaDeviceSynchronize(); sp.gpu2cpu(); finish = clock(); cout<< "Segmentation takes " << ((double)(finish-start)/CLOCKS_PER_SEC) << " sec" << endl; // Part 4: Save the mean/boundary image cudaError_t err_t = cudaDeviceSynchronize(); if (err_t){ std::cerr << "CUDA error after cudaDeviceSynchronize." << std::endl; return 0; } String img_number = img_name.substr (0, img_name.find(".")); Mat border_img = sp.get_img_overlaid(); String fname_res_border = "image/result/"+img_number+"_border.png"; imwrite(fname_res_border, border_img); cout << "saving " << fname_res_border << endl; Mat mean_img = sp.get_img_cartoon(); String fname_res_mean = "image/result/"+img_number+"_mean.png"; imwrite(fname_res_mean, mean_img); cout << "saving " << fname_res_mean << endl << endl; count++; } } return 0; }
//./Sp_demo -i <img_filename> -n <nPixels_on_side> --i_std <i_std> int main( int argc, char** argv ) { // get the image filename, nPixels_in_square_side and i_std // the defaults String filename = "image/2.jpg"; int nPixels_in_square_side = 15; int i_std = 20; for (int i = 1; i < argc; ++i) { std::string arg = argv[i]; if ((arg == "-h") || (arg == "--help")) { show_usage(argv[0]); return 0; } else if ((arg == "-i") || (arg == "--img_filename")) { if (i + 1 < argc) { i++; filename = argv[i]; } else { std::cerr << "--img_filename option requires one argument." << std::endl; return 1; } } else if ((arg == "-n") || (arg == "--nPixels_on_side")) { if (i + 1 < argc) { i++; nPixels_in_square_side = atoi (argv[i]); if (nPixels_in_square_side<3) { std::cerr << "--nPixels_in_square_side option requires nPixels_in_square_side >= 3." << std::endl; return 1; } } else { std::cerr << "--nPixels_on_side option requires one argument." << std::endl; return 1; } } else if (arg == "--i_std") { if (i + 1 < argc) { i++; i_std = atoi (argv[i]); if (i_std<5 || i_std>40) { std::cerr << "--i_std option requires 5<= value <=40." << std::endl; return 1; } } else { std::cerr << "--i_std option requires a number." << std::endl; return 1; } }else{ } } cout << "finish reading the arguments" << endl; Mat image = imread(filename, CV_LOAD_IMAGE_COLOR); // Check for invalid input if(! image.data ){ cout << "Could not open or find the image" << std::endl ; return -1; } cout << "finish reading the image" << endl; //Part 1: Specify the parameters: superpixel_options spoptions = get_sp_options(nPixels_in_square_side, i_std); // Part 2 : prepare for segmentation int dimy = image.rows; int dimx = image.cols; Superpixels sp = Superpixels(dimx, dimy, spoptions); //cout << "finish init sp" << endl; cudaDeviceSynchronize(); sp.load_img((unsigned char*)(image.data)); //cout << "finish loading the image" << endl; // Part 3: Do the superpixel segmentation clock_t start,finish; start = clock(); sp.calc_seg(); cudaDeviceSynchronize(); sp.gpu2cpu(); cudaError_t err_t = cudaDeviceSynchronize(); if (err_t){ std::cerr << "CUDA error after cudaDeviceSynchronize. " << std::endl; return 0; } finish = clock(); cout<< "Segmentation takes " << ((double)(finish-start)/CLOCKS_PER_SEC) << " sec" << endl; // Part 4: Save the mean/boundary image Mat border_img = sp.get_img_overlaid(); String fname_res_border = "image/result/img_border.png"; imwrite(fname_res_border, border_img); cout << "saved " << fname_res_border << endl; Mat mean_img = sp.get_img_cartoon(); String fname_res_mean = "image/result/img_mean.png"; imwrite(fname_res_mean, mean_img); cout << "saving " << fname_res_mean << endl; return 0; }