мне нужно, чтобы получить контур от руки изображения, как правило, я обработать изображение с 4 шагами:OpenCV - как получить лучший контур руки от изображения низкого качества серого?
получают сырое RGB серое изображение от 3-х каналов 1 канал:
cvtColor(sourceGrayImage, sourceGrayImage, COLOR_BGR2GRAY);
использование гауссова размывания фильтр серого изображения:
GaussianBlur(sourceGrayImage, sourceGrayImage, Size(3,3), 0);
двоичное серое изображение, я разделить изображение по высоте, обычно я разделить изображение 6 изображений по его высоте, то каждый из них я пороговый процесса:
// we split source picture to binaryImageSectionCount(here it's 8) pieces by its height, // then we for every piece, we do threshold, // and at last we combine them agin to binaryImage const binaryImageSectionCount = 8; void GetBinaryImage(Mat &grayImage, Mat &binaryImage) { // get every partial gray image's height int partImageHeight = grayImage.rows/binaryImageSectionCount; for (int i = 0; i < binaryImageSectionCount; i++) { Mat partialGrayImage; Mat partialBinaryImage; Rect partialRect; if (i != binaryImageSectionCount - 1) { // if it's not last piece, Rect's height should be partImageHeight partialRect = Rect(0, i * partImageHeight, grayImage.cols, partImageHeight); } else { // if it's last piece, Rect's height should be (grayImage.rows - i * partImageHeight) partialRect = Rect(0, i * partImageHeight, grayImage.cols, grayImage.rows - i * partImageHeight); } Mat partialResource = grayImage(partialRect); partialResource.copyTo(partialGrayImage); threshold(partialGrayImage, partialBinaryImage, 0, 255, THRESH_OTSU); // combin partial binary image to one piece partialBinaryImage.copyTo(binaryImage(partialRect)); ///*stringstream resultStrm; //resultStrm << "partial_" << (i + 1); //string string = resultStrm.str(); //imshow(string, partialBinaryImage); //waitKey(0);*/ } imshow("result binary image.", binaryImage); waitKey(0); return; }
использовать findcontour, чтобы получить самую большую площадь контура:
vector<vector<Point> > contours; findContours(binaryImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
обычно работает хорошо, Но для некоторого низкого качества серого изображения, не работает, как показано ниже:
полный код здесь:
#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
// we split source picture to binaryImageSectionCount(here it's 8) pieces by its height,
// then we for every piece, we do threshold,
// and at last we combine them agin to binaryImage
const binaryImageSectionCount = 8;
void GetBinaryImage(Mat &grayImage, Mat &binaryImage)
{
// get every partial gray image's height
int partImageHeight = grayImage.rows/binaryImageSectionCount;
for (int i = 0; i < binaryImageSectionCount; i++)
{
Mat partialGrayImage;
Mat partialBinaryImage;
Rect partialRect;
if (i != binaryImageSectionCount - 1)
{
// if it's not last piece, Rect's height should be partImageHeight
partialRect = Rect(0, i * partImageHeight, grayImage.cols, partImageHeight);
}
else
{
// if it's last piece, Rect's height should be (grayImage.rows - i * partImageHeight)
partialRect = Rect(0, i * partImageHeight, grayImage.cols, grayImage.rows - i * partImageHeight);
}
Mat partialResource = grayImage(partialRect);
partialResource.copyTo(partialGrayImage);
threshold(partialGrayImage, partialBinaryImage, 0, 255, THRESH_OTSU);
// combin partial binary image to one piece
partialBinaryImage.copyTo(binaryImage(partialRect));
///*stringstream resultStrm;
//resultStrm << "partial_" << (i + 1);
//string string = resultStrm.str();
//imshow(string, partialBinaryImage);
//waitKey(0);*/
}
imshow("result binary image.", binaryImage);
waitKey(0);
return;
}
int main(int argc, _TCHAR* argv[])
{
// get image path
string imgPath("C:\\Users\\Alfred\\Desktop\\gray.bmp");
// read image
Mat src = imread(imgPath);
imshow("Source", src);
//medianBlur(src, src, 7);
cvtColor(src, src, COLOR_BGR2GRAY);
imshow("gray", src);
// do filter
GaussianBlur(src, src, Size(3,3), 0);
// binary image
Mat threshold_output(src.rows, src.cols, CV_8UC1, Scalar(0, 0, 0));
GetBinaryImage(src, threshold_output);
imshow("binaryImage", threshold_output);
// get biggest contour
vector<vector<Point> > contours;
findContours(threshold_output,contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
int biggestContourIndex = 0;
int maxContourArea = -1000;
for (int i = 0; i < contours.size(); i++)
{
if (contourArea(contours[i]) > maxContourArea)
{
maxContourArea = contourArea(contours[i]);
biggestContourIndex = i;
}
}
// show biggest contour
Mat biggestContour(threshold_output.rows, threshold_output.cols, CV_8UC1, Scalar(0, 0, 0));
drawContours(biggestContour, contours, biggestContourIndex, cv::Scalar(255,255,255), 2, 8, vector<Vec4i>(), 0, Point());
imshow("maxContour", biggestContour);
waitKey(0);
}
может кто-нибудь, пожалуйста, помогите мне, чтобы получить лучший результат ручного контура? спасибо !!!
Перед тем, как найти контур, почему бы вам не попробовать некоторые методы предварительной обработки, чтобы улучшить изображение и сделать руку более понятной? –
но какую проработку я должен попробовать для этих двух изображений? Не могли бы вы дать мне несколько советов? – Alfred
Вы можете использовать контрастную адаптивную гистограмму. –