HSV颜色分区参考:
#include
#include
#include
using namespace std;
#define MINAREA 600
int main()
{
IplImage* srcRGB = cvLoadImage("33333.bmp");
IplImage* src= cvCreateImage(cvGetSize(srcRGB), 8, 1);
cvCvtColor(srcRGB, src,CV_RGB2GRAY);
cvNamedWindow("srcRGB", 0);
if(srcRGB!=NULL)
{
cvShowImage("srcRGB",srcRGB);
}
/**********************************转HSV分离通道**********************************/
IplImage* hsv = cvCreateImage(cvGetSize(srcRGB), 8, 3);
cvCvtColor( srcRGB, hsv, CV_BGR2HSV );
IplImage* img_h = cvCreateImage(cvGetSize(src), 8, 1);
IplImage* img_s = cvCreateImage(cvGetSize(src), 8, 1);
IplImage* img_v = cvCreateImage(cvGetSize(src), 8, 1);
cvSplit(hsv, img_h, img_s, img_v, NULL);
cvNamedWindow("img_h", 0);
cvShowImage("img_h", img_h);
cvNamedWindow("img_s", 0);
cvShowImage("img_s", img_s);
cvNamedWindow("img_v", 0);
cvShowImage("img_v", img_v);
cvNamedWindow("Thresh", 0);
IplImage* Thresh_img2 = cvCreateImage(cvGetSize(src), 8, 1);
IplImage* Thresh_img1 = cvCreateImage(cvGetSize(src), 8, 1);
IplImage* Thresh_img = cvCreateImage(cvGetSize(src), 8, 1);
cvThreshold(img_s, Thresh_img1, 90, 255, CV_THRESH_BINARY);
cvErode( Thresh_img1, Thresh_img1, NULL, 2 );
cvDilate(Thresh_img1, Thresh_img1, NULL, 2);
cvNamedWindow("img_ED", 0);
cvShowImage("img_ED", Thresh_img1);
cvShowImage("Thresh", Thresh_img1);
cvWaitKey(0);
cvThreshold(img_v, Thresh_img2, 248, 255, CV_THRESH_BINARY);
cvAdd(Thresh_img1,Thresh_img2, Thresh_img);
cvNamedWindow("img_ADD", 0);
cvShowImage("img_ADD", Thresh_img);
/***********************************提取目标*************************************/
IplImage* temp = cvCreateImage(cvGetSize(src), 8, 1);
IplImage* dst = cvCreateImage(cvGetSize(src), 8, 1);
IplImage* dstRGB = cvCreateImage(cvGetSize(src), 8, 3);
cvZero(dstRGB);
cvZero(temp);
cvZero(dst);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contour = 0;
CvPoint center[20] = {cvPoint(0,0)};
int contour_num = cvFindContours(Thresh_img1, storage, &contour, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for(int i = 0; contour != 0; contour = contour->h_next, i++ )
{
double length = cvArcLength(contour);
if(length < MINAREA)
{
cvSeqRemove(contour, 0); // 删除面积小于设定值的轮廓
continue;
}
int count = 0;
if(length >= MINAREA)
{
count++;
cvDrawContours(temp, contour, cvScalar(255,255,255), cvScalar(255,255,255), -1,CV_FILLED); //作为掩码
cvCopy(img_h, dst, temp);
// cvSeqRemove(contour->h_prev, 0);
///////////////////////////////目标区域hue通道的平均灰度值////////////////////////////////////
int pix_count=0;
int gray_value = 0;
for(int x=0; xheight; x++)
{
uchar* ptr = (uchar*) dst->imageData+x*dst->widthStep;
for(int y=0; ywidth; y++)
{
if(ptr[y])
{
gray_value += ptr[y];
pix_count++;
}
}
}
gray_value/=pix_count;
/////////////////////////////////////找目标中心//////////////////////////////////////
CvSeqReader reader;
CvPoint pt = cvPoint(0,0);
cvStartReadSeq(contour, &reader);
int point_count = 0;
for(int i=0; itotal; i++)
{
CV_READ_SEQ_ELEM(pt, reader);
center[count].x+=pt.x;
center[count].y+=pt.y;
point_count++;
}
center[count].x=center[count].x/point_count; //中心坐标
center[count].y=center[count].y/point_count;
cout<<"X:"<
#include "stdafx.h"
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
double GetP2PDis(Point2d p1, Point2d p2);
int FuncCountHSV(Mat mat);
int _tmain(int argc, _TCHAR* argv[])
{
Mat img = imread("01.bmp");
Mat imgSrc;
img.copyTo(imgSrc);
double time0 = static_cast(getTickCount()); //起始时间
const Size size = img.size();
int height = size.height;
int width = size.width;
//---To HSV---//
Mat hsv = Mat::zeros(height, width, CV_8UC3);
cvtColor(imgSrc, hsv, CV_RGB2HSV);
//---分离通道---//
vector mv;
Mat hsv_h = Mat::zeros(height, width, CV_8UC1);
Mat hsv_s = Mat::zeros(height, width, CV_8UC1);
Mat hsv_v = Mat::zeros(height, width, CV_8UC1);
split(hsv, mv);
hsv_h = mv.at(0);
hsv_s = mv.at(1);
hsv_v = mv.at(2);
//---S-处理---//
Mat matS1 = Mat::zeros(height, width, CV_8UC1);
Mat matS2 = Mat::zeros(height, width, CV_8UC1);
Mat matS3 = Mat::zeros(height, width, CV_8UC1);
Mat element_Se = getStructuringElement(MORPH_ELLIPSE,Size(5,5));
Mat element_Sd = getStructuringElement(MORPH_ELLIPSE,Size(5,5));
threshold(hsv_s, matS1, 90, 255, CV_THRESH_BINARY);
erode( matS1, matS2, element_Se);
dilate(matS2, matS3, element_Sd);
//---V-处理---//
Mat matV1 = Mat::zeros(height, width, CV_8UC1);
threshold(hsv_v, matV1, 248, 255, CV_THRESH_BINARY);
//---叠加----//
Mat matAdd = Mat::zeros(height, width, CV_8UC1);
add(matS3, matV1, matAdd);
Mat imgDst = matAdd;
vector > contours;
vector hierarchy;
findContours(imgDst, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0,0));
size_t nContoursNum = contours.size();
cout << "轮廓数量:" << nContoursNum << endl;
namedWindow("Test1", 0);
resizeWindow("Test1", 300, 200);
size_t RstNum = 0;
for ( size_t index = 0; index < nContoursNum; index++ )
{
size_t nPerSum = contours[index].size();
double dPerimeter = 0.0; // 轮廓周长
for ( size_t i=0; i < nPerSum; i++ )
{
//----计算周长----//
double dCurDis = 0.0;
if ( i < nPerSum - 1)
{
dCurDis = GetP2PDis(contours[index].at(i), contours[index].at(i+1) );
}
else
{
dCurDis = GetP2PDis(contours[index].at(i), contours[index].at(0) );
}
dPerimeter += dCurDis;
}
if ( dPerimeter > 600 )
{
RstNum++;
//-----计算中心坐标-----//
int nMinX = contours[index].at(0).x;
int nMinY = contours[index].at(0).y;
int nMaxX = contours[index].at(0).x;
int nMaxY = contours[index].at(0).y;
double dSumH = 0.0;
for (size_t i = 1; i < nPerSum; i++ )
{
if ( contours[index].at(i).x > nMaxX ) nMaxX = contours[index].at(i).x;
if ( contours[index].at(i).y > nMaxY ) nMaxY = contours[index].at(i).y;
if ( contours[index].at(i).x < nMinX ) nMinX = contours[index].at(i).x;
if ( contours[index].at(i).y < nMinY ) nMinY = contours[index].at(i).y;
//dSumH += imgSrc.ptr(contours[index].at(i).y)[contours[index].at(i).x];
}
Point center;
center.x = nMinX + (nMaxX - nMinX) / 2;
center.y = nMinY + (nMaxY - nMinY) / 2;
cout << "Num: " << RstNum << " Points" << nPerSum << " Length:" << dPerimeter << "----X:" << center.x << " Y:" << center.y<< endl;
//------统计颜色-----//
int colWidth = (nMaxX - nMinX);
int colHeight = (nMaxY - nMinY);
Mat matColorH = Mat::zeros(colWidth, colHeight, CV_8UC1);
Mat matColorS = Mat::zeros(colWidth, colHeight, CV_8UC1);
Mat matColorV = Mat::zeros(colWidth, colHeight, CV_8UC1);
Rect rectROI( nMinX, nMinY, colWidth, colHeight );
hsv_h(rectROI).convertTo(matColorH, matColorH.type(), 1, 0);
hsv_s(rectROI).convertTo(matColorS, matColorS.type(), 1, 0);
hsv_v(rectROI).convertTo(matColorV, matColorV.type(), 1, 0);
Scalar mean_h = mean(matColorH);
Scalar mean_s = mean(matColorS);
Scalar mean_v = mean(matColorV);
double dH = mean_h[0];
double dS = mean_s[0];
double dV = mean_v[0];
cout << "H:" << dH << " S:" << dS << " V:" << dV;
// if ( dH>0 && dH<180 && dS>0 && dS<255 && dV>0 && dV<46 ) cout << "01黑色 ";
// if ( dH>0 && dH<180 && dS>0 && dS<43 && dV>46 && dV<220 ) cout << "02灰色 ";
// if ( dH>0 && dH<180 && dS>0 && dS<30 && dV>221 && dV<255 ) cout << "03白色 ";
// if ( dH>0 && dH<10 && dS>43 && dS<255 && dV>46 && dV<255 ) cout << "04红色 ";
// if ( dH>156 && dH<180 && dS>43 && dS<255 && dV>46 && dV<255 ) cout << "04红色2 ";
// if ( dH>11 && dH<25 && dS>43 && dS<255 && dV>46 && dV<255 ) cout << "05橙色 ";
// if ( dH>26 && dH<34 && dS>43 && dS<255 && dV>46 && dV<255 ) cout << "06黄色 ";
// if ( dH>35 && dH<77 && dS>43 && dS<255 && dV>46 && dV<255 ) cout << "07绿色 ";
// if ( dH>78 && dH<99 && dS>43 && dS<255 && dV>46 && dV<255 ) cout << "08青色 ";
// if ( dH>100 && dH<124 && dS>43 && dS<255 && dV>46 && dV<255 ) cout << "09蓝色 ";
// if ( dH>125 && dH<155 && dS>43 && dS<255 && dV>46 && dV<255 ) cout << "10紫色 ";
if ( dH>0 && dH<180 )
{
if ( dH>0 && dH<=10 ) cout << "04红色 ";
if ( dH>10 && dH<=25 ) cout << "05橙色 ";
if ( dH>25 && dH<=34 ) cout << "06黄色 ";
if ( dH>34 && dH<=77 ) cout << "07绿色 ";
if ( dH>77 && dH<=99 ) cout << "08青色 ";
if ( dH>99 && dH<=124 ) cout << "09蓝色 ";
if ( dH>124 && dH<=155 ) cout << "10紫色 ";
if ( dH>155 && dH<=180 ) cout << "04红色2 ";
if ( dH>0 && dH<180 && dS>0 && dS<255 && dV>0 && dV<46 ) cout << "01黑色 ";
if ( dH>0 && dH<180 && dS>0 && dS<43 && dV>46 && dV<220 ) cout << "02灰色 ";
if ( dH>0 && dH<180 && dS>0 && dS<43 && dV>221 && dV<255 ) cout << "03白色 ";
}
cout << endl;
cout << endl;
imshow("Test1", matColorH);
waitKey();
// imshow("Test1", matColorS);
// waitKey();
// imshow("Test1", matColorV);
// waitKey();
//----绘制结果轮廓----//
Scalar color( rand()&255, rand()&255, rand()&255 );
drawContours( imgSrc, contours, index, color, 10, 8, hierarchy );
circle(imgSrc, center, 5 , color, 5, 8, 0);
char str_i[10];
sprintf(str_i,"%d",RstNum);
putText(imgSrc, str_i, center, CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0,255,0), 2, 8);
imwrite("result.bmp", imgSrc);
}
}
time0 = ((double)getTickCount() - time0) / getTickFrequency(); //运行后时间
cout << "Run time : " << time0 << endl;
// imshow("Test1", hsv);
// waitKey();
//
// imshow("Test1", hsv_h);
// waitKey();
// imshow("Test1", hsv_s);
// waitKey();
// imshow("Test1", hsv_v);
// waitKey();
//
// imshow("Test1", matS1);
// waitKey();
// imshow("Test1", matS2);
// waitKey();
// imshow("Test1", matS3);
// waitKey();
//
// imshow("Test1", matV1);
// waitKey();
// imshow("Test1", matV2);
// waitKey();
// imshow("Test1", matV3);
// waitKey();
//
// imshow("Test1", matAdd);
// waitKey();
// imshow("Test1", imgDst);
// waitKey();
imshow("Test1", imgSrc);
waitKey();
return 0;
}
double GetP2PDis(Point2d p1, Point2d p2)
{
double dDis = 0.0;
dDis = sqrt((p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y));
return dDis;
}
//----------------------------------------------
Camera.Size size = mCamera.getParameters().getPreviewSize();
final int w = size.width;
final int h = size.height;
final YuvImage image = new YuvImage(mData, ImageFormat.NV21, w, h, null);
ByteArrayOutputStream os = new ByteArrayOutputStream(mData.length);
if (!image.compressToJpeg(new Rect(0, 0, w, h), 100, os)) {
return;
}
byte[] tmp = os.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(tmp, 0, tmp.length);
Bitmap input = rotateBitmap(bitmap, 90);
Bitmap bmp = input.copy(Bitmap.Config.ARGB_8888, true);
int nw = bmp.getWidth();
int nh = bmp.getHeight();
int[] pix = new int[nw * nh];
bmp.getPixels(pix, 0, nw, 0, 0, nw, nh);
int[] resultPixels = OpenCVHelper.colorDetection(pix, nw, nh);
Bitmap result = Bitmap.createBitmap(nw, nh, Bitmap.Config.RGB_565);
result.setPixels(resultPixels,0,nw,0,0,nw,h);
image_show.setImageBitmap(result);
JNIEXPORT jintArray JNICALL Java_com_example_targetlocationapp_OpenCVHelper_colorDetection
(JNIEnv *env, jclass obj, jintArray buf, jint w, jint h){
jint *cbuf;
cbuf = env->GetIntArrayElements(buf,JNI_FALSE);
if (NULL == cbuf)
{
return 0;
}
Mat srcImage(h,w,CV_8UC4,(unsigned char*) cbuf);
Mat rgbImage;
cvtColor(srcImage, rgbImage, COLOR_BGRA2RGB);
for (size_t i = 0; i < 5; i++)
{
Point center(100 + 50*i, 150 + 30*i);
ellipse(rgbImage, center, Size(100, 150), 0, 0, 360, Scalar(255, 0, 255), 4, 8, 0);
}
int size = w * h;
jintArray result = env->NewIntArray(size);
//jint *pArrayBuf = env->GetIntArrayElements(result, nullptr);
u_char *ptr = rgbImage.ptr(0);
u_char *ptrRst = srcImage.ptr(0);
for(int i=0;i < size; i++){
// int grayScale = (int)(ptr[3*i+2]*0.299 + ptr[3*i+1]*0.587 + ptr[3*i+0]*0.144 );
// pArrayBuf[i] = (int)ptr[3*i+2];
ptrRst[4*i+0] = (int)ptr[3*i+2];
ptrRst[4*i+1] = (int)ptr[3*i+1];
ptrRst[4*i+2] = (int)ptr[3*i+0];
}
env->SetIntArrayRegion(result,0,size,cbuf);
env->ReleaseIntArrayElements(buf,cbuf,0);
return result;
}
JNIEXPORT jintArray JNICALL Java_com_example_app_OpenCVHelper_colorDet
(JNIEnv *env, jclass obj, jbyteArray yuv, jint w, jint h){
jbyte * pBuf = (jbyte*)env->GetByteArrayElements(yuv, 0);
int width = w;
int height = h + h /2;
cv::Mat imageSrc(height, width , CV_8UC1, (unsigned char*)pBuf );
cv::Mat imageBGR;
cv::cvtColor(imageSrc, imageBGR, CV_YUV2BGR_NV21); //将YUV转换成BGR
cv::Mat srcSize;
cv::resize(imageBGR, srcSize, Size(h/20, w/20));
cv::Mat timage;
cv::transpose(imageBGR, timage); //图像转置
cv::Mat yimage;
cv::flip(timage, yimage, 1); //Y方向镜像
//---------图像处理---------
cv::Mat image(yimage);
cv::Mat frameHSV;
cv::medianBlur(image, image, 5);
cv::cvtColor(image, frameHSV, CV_BGR2HSV);
cv::Mat dstTemp1(image.rows, image.cols, CV_8UC1);
cv::Mat dstTemp2(image.rows, image.cols, CV_8UC1);
cv::inRange(frameHSV, Scalar(0,30,30), Scalar(40,170,256), dstTemp1);
cv::inRange(frameHSV, Scalar(156, 30, 30), Scalar(180, 170, 256), dstTemp2);
cv::Mat mask(image.rows, image.cols, CV_8UC1); // 2值掩膜
cv::add(dstTemp1, dstTemp2, mask);
// 形态学操作,去除噪声,并使手的边界更加清晰
cv::Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
cv::erode(mask, mask, element);
cv::morphologyEx(mask, mask, MORPH_OPEN, element);
cv::dilate(mask, mask, element);
cv::morphologyEx(mask, mask, MORPH_CLOSE, element);
cv::vector> contours; // 轮廓
cv::vector hierarchy; // 轮廓的结构信息
cv::vector> filterContours; // 筛选后的轮廓
contours.clear();
hierarchy.clear();
filterContours.clear();
Mat maskDst = mask;
// 得到手的轮廓
//CV_RETR_EXTERNAL 只检测出最外轮廓即c0。图2中第一个轮廓指向最外的序列,除此之外没有别的连接。
//CV_RETR_LIST 检测出所有的轮廓并将他们保存到表(list)中,图2中描绘了这个表,被找到的9条轮廓相互之间由h_prev和h_next连接。
//CV_RETR_COMP 检测出所有的轮廓并将他们组织成双层的结构,第一层是外部轮廓边界,第二层边界是孔的边界。
//CV_RETR_TREE 检测出所有轮廓并且重新建立网状的轮廓结构。
cv::findContours(mask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
size_t nContoursNum = contours.size();
size_t nCountNum = 0;
// 去除伪轮廓
cv::Mat dst(image.rows, image.cols, CV_8UC3);
for (size_t i = 0; i < contours.size(); i++)
{
cv::Scalar color(rand() & 255, rand() & 255, rand() & 255);
cv::drawContours(dst, contours, i, color, CV_FILLED, 8, hierarchy);
}
cv::Mat dstSize;
cv::resize(dst, dstSize, Size(h, w));
const int size = w * h;
jintArray result = env->NewIntArray(size);
jint* pArrayBuf = env->GetIntArrayElements(result, nullptr);
Mat dstShow(h, w, CV_8UC4, (unsigned char* )pArrayBuf);
u_char* ptr = dstSize.ptr(0);
u_char* ptrRst = dstShow.ptr(0);
for(int i=0;iSetIntArrayRegion(result, 0, size, pArrayBuf);
env->ReleaseIntArrayElements(result, pArrayBuf, 0);
env->ReleaseByteArrayElements(yuv, pBuf, 0);
return result;
}