I need to get contour from hand image, usually I process image with 4 steps:
我需要从手部图像获取轮廓,通常我用4个步骤处理图像:
-
get raw RGB gray image from 3 channels to 1 channel:
从3个通道到1个通道获取原始RGB灰度图像:
cvtColor(sourceGrayImage, sourceGrayImage, COLOR_BGR2GRAY);
-
use Gaussian blur to filter gray image:
使用高斯模糊过滤灰度图像:
GaussianBlur(sourceGrayImage, sourceGrayImage, Size(3,3), 0);
-
binary gray image, I split image by height, normally I split image to 6 images by its height, then each one I do threshold process:
二进制灰度图像,我按高度分割图像,通常我将图像按其高度分割为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; }
-
use findcontour to get biggest area contour:
使用findcontour获得最大的区域轮廓:
vector<vector<Point> > contours; findContours(binaryImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
normally it works well, But for some low quality gray image, it doesn't work,like below:
通常它运作良好,但对于一些低质量的灰色图像,它不起作用,如下所示:
the complete code is here:
完整的代码在这里:
#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);
}
could anybody please help me to get a better hand contour result? thanks!!!
请问有谁能帮助我获得更好的手部轮廓效果?谢谢!!!
1 个解决方案
#1
1
I have the code snippet in python, you can follow the same approach in C:
我在python中有代码片段,你可以在C中遵循相同的方法:
img = cv2.imread(x, 1)
cv2.imshow("img",img)
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow("gray",imgray)
#Code for histogram equalization
equ = cv2.equalizeHist(imgray)
cv2.imshow('equ', equ)
#Code for contrast limited adaptive histogram equalization
#clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
#cl2 = clahe.apply(imgray)
#cv2.imshow('clahe2', cl2)
This is the result I obtained:
这是我获得的结果:
If you're image is horribly bad you could try the code that I commented involving contrast limited adaptive histogram equalization.
如果您的图像非常糟糕,您可以尝试我评论的代码,包括对比度限制自适应直方图均衡。
#1
1
I have the code snippet in python, you can follow the same approach in C:
我在python中有代码片段,你可以在C中遵循相同的方法:
img = cv2.imread(x, 1)
cv2.imshow("img",img)
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow("gray",imgray)
#Code for histogram equalization
equ = cv2.equalizeHist(imgray)
cv2.imshow('equ', equ)
#Code for contrast limited adaptive histogram equalization
#clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
#cl2 = clahe.apply(imgray)
#cv2.imshow('clahe2', cl2)
This is the result I obtained:
这是我获得的结果:
If you're image is horribly bad you could try the code that I commented involving contrast limited adaptive histogram equalization.
如果您的图像非常糟糕,您可以尝试我评论的代码,包括对比度限制自适应直方图均衡。