65,187
社区成员




#include <iostream>
#include <string>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <imageAlgorithm.hpp>
//not a big deal to use global parameter or
//global typedef in this small program
typedef std::vector<std::vector<cv::Point> > ContoursType;
std::string const Folder("/Users/Qt/program/blogsCodes/pic/");
/**
* @brief segment all of the leafs
* @param the number of the images want to segment
* @return the leafs
*/
std::vector<cv::Mat> contours_method(std::initializer_list<std::string> number)
{
std::vector<cv::Mat> results;
for(auto const &num : number){
cv::Mat color_image = cv::imread(Folder + "leaf" + num + ".png");
if(color_image.empty()){
std::cerr<<"input is empty"<<std::endl;
return results;
}
cv::Mat image;
cv::cvtColor(color_image, image, CV_BGR2GRAY);
//step 1 : binarize the image
cv::Mat binary;
cv::threshold(image, binary, 140, 255, cv::THRESH_BINARY);
//step 2 : remove small objects and noise
auto const structure = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5));
cv::Mat fore_ground;
cv::erode(binary, fore_ground, structure, cv::Point(-1, -1), 4);
//step 3 : find possible foreground(set as 255)
ContoursType contours;
cv::findContours(fore_ground, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
OCV::remove_contours(contours, 8000, 50000);
fore_ground.setTo(0);
cv::drawContours(fore_ground, contours, -1, cv::Scalar(255), CV_FILLED);
cv::imwrite("foregroundFinal" + num + ".png", fore_ground);
//step 4 : find possible background(set as 128)
//0 represent uncertain pixels
cv::Mat back_ground;
cv::dilate(binary, back_ground, structure, cv::Point(-1, -1), 4);
cv::threshold(back_ground, back_ground, 1, 128, cv::THRESH_BINARY_INV);
cv::imwrite("backGround" + num + ".png", back_ground);
//step 5 : create markers and mask
cv::Mat markers = back_ground + fore_ground;
cv::imwrite("markers" + num + ".png", markers);
cv::Mat mask;
markers.convertTo(mask, CV_32S);
cv::watershed(color_image, mask);
mask.convertTo(mask, CV_8U);
cv::threshold(mask, mask, 150, 255, CV_THRESH_BINARY);
cv::imwrite("mask" + num + ".png", mask);
//step 6 : final results
cv::Mat result;
cv::imwrite("finalMask" + num + ".png", mask);
color_image.copyTo(result, mask);
cv::imwrite("result" + num + ".png", result);
results.push_back(result);
}
return results;
}
/**
* @brief cut the leafs to single leaf
* @param input input image
* @param name name of the image want to be saved
*/
void cut_to_single_leaf_simple(cv::Mat const &input, std::string const &name)
{
cv::Mat mask;
//step 1 : convert the input to gray image
cv::cvtColor(input, mask, CV_BGR2GRAY);
//step 2 : binarize it
cv::threshold(mask, mask, 128, 255, CV_THRESH_BINARY);
//step 3 : do serious erosion
cv::erode(mask, mask, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)), cv::Point(-1, -1), 5);
//step 4 : find and remove the outliers contours
ContoursType contours;
cv::findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
OCV::remove_contours(contours, 500, 120000);
cv::Mat result;
//step 5 : draw the contours one by one
for(size_t i = 0; i != contours.size(); ++i){
mask.setTo(0);
cv::drawContours(mask, contours, i, cv::Scalar(255), CV_FILLED);
//step 6 : dilate and close the contours
cv::dilate(mask, mask, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)), cv::Point(-1, -1), 6);
cv::morphologyEx(mask, mask, CV_MOP_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15)));
input.copyTo(result, mask);
cv::imwrite(name + std::to_string(i) + ".png", result);
//cv::imshow("", result);
//cv::waitKey();
result.setTo(0);
}
}
int main()
{
std::vector<cv::Mat> results = contours_method({"01"});
cut_to_single_leaf_simple(results[1], "singleLeaf01_");
return 0;
}
/**
* @brief remove the contours by contours area(pixels surrounded by the contours)
* @param contours : the contours
* @param cmin : contour size lower than cmin will be removed
* @param cmax : contour size higher than cmax will be removed
*/
void remove_contours(std::vector<std::vector<cv::Point> > &contours, double cmin, double cmax)
{
auto it = std::partition(std::begin(contours), std::end(contours), [=](std::vector<cv::Point> const &data)
{
auto const size = cv::contourArea(data);
return !(size < cmin || size > cmax);
});
contours.erase(it, std::end(contours));
}
void remove_contours(ContoursType &contours, double cmin, double cmax)
{
auto it = std::begin(contours);
while(it != std::end(contours)){
auto size = cv::contourArea(*it);
if(size < cmin || size > cmax){
it = contours.erase(it);
}else{
++it;
}
}
}
remove_contours(contours, 10000, 50000);
#include <iostream>
#include <string>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
typedef std::vector<std::vector<cv::Point> > ContoursType;
//not a big deal to use global parameter in this small program
std::string const Folder("/Users/Qt/program/blogsCodes/pic/");
void remove_contours(ContoursType &contours, ContoursType::size_type cmin, ContoursType::size_type cmax)
{
auto it = std::begin(contours);
while(it != std::end(contours)){
auto const size = it->size();
if(size < cmin || size > cmax){
it = contours.erase(it);
}else{
++it;
}
}
}
int main()
{
cv::Mat image = cv::imread(Folder + "leaf02.png", 0);
if(image.empty()){
std::cerr<<"input is empty"<<std::endl;
return -1;
}
cv::imshow("image", image);
cv::Mat binary;
//cv::threshold(image, binary, 0, 255, cv::THRESH_BINARY + cv::THRESH_OTSU);
cv::threshold(image, binary, 140, 255, cv::THRESH_BINARY);
auto const structure = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7));
cv::erode(binary, binary, structure);
//cv::morphologyEx(binary, binary, cv::MORPH_OPEN, structure);
cv::imshow("binary", binary);
ContoursType contours;
cv::findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
remove_contours(contours, 600, 3000);
cv::Mat result(image.size(), CV_8U, cv::Scalar(255));
cv::drawContours(result, contours, -1, cv::Scalar(0), 2);
cv::imshow("result", result);
cv::waitKey();
return 0;
}
还有watershed,canny等方法没尝试
楼主如果不舍得花钱,可以找大学专门搞computer vision的实验室帮忙吧?
第一,二线线的大学研究室应该有足够的能力解决这种问题的