#include "highgui.h"
#include "cv.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
// 求最大值max,最小值min,绝对值abs,正负标志sign
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(x) ((x) > 0 ? (x) : -(x))
#define sign(x) ((x) > 0 ? 1 : -1)
//物体位移动的最小值和最大值
#define STEP_MIN 5
#define STEP_MAX 100
IplImage *image;
// 物体放置地点
CvPoint objectPos = cvPoint(-1, -1);
// 被跟踪的颜色和允许范围---------------可调--------------------
int h = 0, s = 0, v = 0, tolerance =5;
int H_slider_pos=173,S_slider_pos=150,V_slider_pos=255;
/*
* 功能:将原图转换为二值图
* 输入:image图片,被检测的像素值nbPixels
* 输出:被检测物体的重心
*/
CvPoint binarisation(IplImage* image, int *nbPixels) {
int x, y;
CvScalar pixel;
IplImage *hsv, *mask;
IplConvKernel *kernel;
int sommeX = 0, sommeY = 0;
*nbPixels = 0;
// 创建一个mask图像
mask = cvCreateImage(cvGetSize(image), image->depth, 1);
//得到hsv格式图像
hsv = cvCloneImage(image);
cvCvtColor(image, hsv, CV_BGR2HSV);
//按照颜色范围给mask图像赋值(像素值在范围内则被置为0xff)
cvInRangeS(hsv, cvScalar(h - tolerance -1, s - 5*tolerance, 0), cvScalar(h + tolerance -1, s + 5*tolerance, 255), mask);
//创建结构元素----一个5X5的椭圆,锚点在(2,2)
kernel = cvCreateStructuringElementEx(5, 5, 2, 2, CV_SHAPE_ELLIPSE);
//膨胀
cvDilate(mask, mask, kernel, 1);
//腐蚀
cvErode(mask, mask, kernel, 1);
//计算出查找的重心
for(x = 0; x < mask->width; x++) {
for(y = 0; y < mask->height; y++) {
//计算符合的像素点的个数 和X,Y值的和
if(((uchar *)(mask->imageData + y*mask->widthStep))[x] == 255) {
sommeX += x;
sommeY += y;
(*nbPixels)++;
}
}
}
//显示mask图像
cvShowImage("视频二值化", mask);
//释放结构元素
cvReleaseStructuringElement(&kernel);
//释放mask图像内存
cvReleaseImage(&mask);
//释放hsv图像内存
cvReleaseImage(&hsv);
//如果找到了符合的点,将所有的点的X,Y坐标求均值并返回
if(*nbPixels > 0)
return cvPoint((int)(sommeX / (*nbPixels)), (int)(sommeY / (*nbPixels)));
else
return cvPoint(-1, -1);
}
/*
* 功能:在被跟踪的物体重心上画圆
* 输入:image图片,物体重心objectNextPos,像素点个数nbPixels
* 输出:无
*/
void addObjectToVideo(IplImage* image, CvPoint objectNextPos, int nbPixels)
{
int objectNextStepX, objectNextStepY;
// 计算下一个红点位置
if (nbPixels > 10)
{
if (objectPos.x == -1 || objectPos.y == -1)
{
objectPos.x = objectNextPos.x;
objectPos.y = objectNextPos.y;
}
if (abs(objectPos.x - objectNextPos.x) > STEP_MIN)
{
objectNextStepX = max(STEP_MIN, min(STEP_MAX, abs(objectPos.x - objectNextPos.x) / 2));
objectPos.x += (-1) * sign(objectPos.x - objectNextPos.x) * objectNextStepX;
}
if (abs(objectPos.y - objectNextPos.y) > STEP_MIN) {
objectNextStepY = max(STEP_MIN, min(STEP_MAX, abs(objectPos.y - objectNextPos.y) / 2));
objectPos.y += (-1) * sign(objectPos.y - objectNextPos.y) * objectNextStepY;
}
} else {
objectPos.x = -1;
objectPos.y = -1;
}
// 在image图像上画一个半径为15的红色圆点
if (nbPixels > 10)
cvDrawCircle(image, objectPos, 10, CV_RGB(255, 0, 0), -1);
/*CvFont* font;
char string[]="i am happy";
cvInitFont(font,CV_FONT_HERSHEY_SIMPLEX,1.0f,1.0f,0,1,8);
cvPutText(image,string,objectPos,font,CV_RGB(0,0,255));
*/
cvShowImage("动态追踪", image);
}
/*
* 功能:得到鼠标点击处的像素值(被跟踪的像素值)
* 输入:event事件,坐标x,y ,标志flags,属性指针param
* 输出:无
*/
void getObjectColor(int event, int x, int y, int flags, void *param = NULL) {
// 定义一个var[4]数组变量pixel
CvScalar pixel;
//定义hsv图像
IplImage *hsv;
//鼠标按下
if(event == CV_EVENT_LBUTTONUP){
// 获取hsv图像
hsv = cvCloneImage(image);
cvCvtColor(image, hsv, CV_BGR2HSV);
// 获取像素值
pixel = cvGet2D(hsv, y, x);
h = (int)pixel.val[0];
s = (int)pixel.val[1];
v = (int)pixel.val[2];
printf("%d\n",hsv->depth);
printf("%d,%d,%d\n",h,s,v);
// 释放image内存
cvReleaseImage(&hsv);
}
}
//修改HSV值
void H_changed(int pos)
{
h=H_slider_pos;
}
void S_changed(int pos)
{
s=S_slider_pos;
}
void V_changed(int pos)
{
v=V_slider_pos;
}
/*****************************************
主程序
******************************************/
int main() {
IplImage *hsv;
CvCapture *capture;
char key=NULL;
int nbPixels;
CvPoint objectNextPos;
// 读取摄像头
capture = cvCreateCameraCapture(1);
// 检测摄像头捕获是否成功
if (!capture) {
printf("Can't initialize the video capture.\n");
return -1;
}
// 创建两个视频窗口
cvNamedWindow("动态追踪", CV_WINDOW_AUTOSIZE);
cvNamedWindow("视频二值化", CV_WINDOW_AUTOSIZE);
cvMoveWindow("动态追踪", 0, 100);
cvMoveWindow("视频二值化", 650, 100);
//创建颜色控制的滚动条
//cvCreateTrackbar("H:","GeckoGeek Mask",&H_slider_pos,255,H_changed);
//cvCreateTrackbar("S:","GeckoGeek Mask",&S_slider_pos,255,S_changed);
//cvCreateTrackbar("V:","GeckoGeek Mask",&V_slider_pos,255,V_changed);
/*
// 点击鼠标选择被跟踪的颜色
cvSetMouseCallback("GeckoGeek Color Tracking", getObjectColor);
*/
/*
//红瓶盖
h=174;
s=146;
v=160;
*/
/*
//红瓶盖
h=171;
s=151;
v=84;
*/
/*
//皮肤
h=11;
s=51;
v=124;
*/
/*
//激光1
h=173;
s=150;//s最大值190,最小值130
v=255;
*/
/*
//激光2
h=173;
s=150;
v=255;
*/
// 按Q退出
while(key != 'Q' && key != 'q') {
// 得到当前图像
image = cvQueryFrame(capture);
// 若无图像,退出当前循环继续获取图像
if(!image)
continue;
//得到被检测的颜色重心
objectNextPos = binarisation(image, &nbPixels);
//添加红色圆点到被检测颜色的重心
addObjectToVideo(image, objectNextPos, nbPixels);
//等待10ms
key = cvWaitKey(10);
}
// 销毁窗口
cvDestroyWindow("动态追踪");
cvDestroyWindow("视频二值化");
// 释放capture资源
cvReleaseCapture(&capture);
return 0;
}
#include "cv.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
// 求最大值max,最小值min,绝对值abs,正负标志sign
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(x) ((x) > 0 ? (x) : -(x))
#define sign(x) ((x) > 0 ? 1 : -1)
//物体位移动的最小值和最大值
#define STEP_MIN 5
#define STEP_MAX 100
IplImage *image;
// 物体放置地点
CvPoint objectPos = cvPoint(-1, -1);
// 被跟踪的颜色和允许范围---------------可调--------------------
int h = 0, s = 0, v = 0, tolerance =5;
int H_slider_pos=173,S_slider_pos=150,V_slider_pos=255;
/*
* 功能:将原图转换为二值图
* 输入:image图片,被检测的像素值nbPixels
* 输出:被检测物体的重心
*/
CvPoint binarisation(IplImage* image, int *nbPixels) {
int x, y;
CvScalar pixel;
IplImage *hsv, *mask;
IplConvKernel *kernel;
int sommeX = 0, sommeY = 0;
*nbPixels = 0;
// 创建一个mask图像
mask = cvCreateImage(cvGetSize(image), image->depth, 1);
//得到hsv格式图像
hsv = cvCloneImage(image);
cvCvtColor(image, hsv, CV_BGR2HSV);
//按照颜色范围给mask图像赋值(像素值在范围内则被置为0xff)
cvInRangeS(hsv, cvScalar(h - tolerance -1, s - 5*tolerance, 0), cvScalar(h + tolerance -1, s + 5*tolerance, 255), mask);
//创建结构元素----一个5X5的椭圆,锚点在(2,2)
kernel = cvCreateStructuringElementEx(5, 5, 2, 2, CV_SHAPE_ELLIPSE);
//膨胀
cvDilate(mask, mask, kernel, 1);
//腐蚀
cvErode(mask, mask, kernel, 1);
//计算出查找的重心
for(x = 0; x < mask->width; x++) {
for(y = 0; y < mask->height; y++) {
//计算符合的像素点的个数 和X,Y值的和
if(((uchar *)(mask->imageData + y*mask->widthStep))[x] == 255) {
sommeX += x;
sommeY += y;
(*nbPixels)++;
}
}
}
//显示mask图像
cvShowImage("视频二值化", mask);
//释放结构元素
cvReleaseStructuringElement(&kernel);
//释放mask图像内存
cvReleaseImage(&mask);
//释放hsv图像内存
cvReleaseImage(&hsv);
//如果找到了符合的点,将所有的点的X,Y坐标求均值并返回
if(*nbPixels > 0)
return cvPoint((int)(sommeX / (*nbPixels)), (int)(sommeY / (*nbPixels)));
else
return cvPoint(-1, -1);
}
/*
* 功能:在被跟踪的物体重心上画圆
* 输入:image图片,物体重心objectNextPos,像素点个数nbPixels
* 输出:无
*/
void addObjectToVideo(IplImage* image, CvPoint objectNextPos, int nbPixels)
{
int objectNextStepX, objectNextStepY;
// 计算下一个红点位置
if (nbPixels > 10)
{
if (objectPos.x == -1 || objectPos.y == -1)
{
objectPos.x = objectNextPos.x;
objectPos.y = objectNextPos.y;
}
if (abs(objectPos.x - objectNextPos.x) > STEP_MIN)
{
objectNextStepX = max(STEP_MIN, min(STEP_MAX, abs(objectPos.x - objectNextPos.x) / 2));
objectPos.x += (-1) * sign(objectPos.x - objectNextPos.x) * objectNextStepX;
}
if (abs(objectPos.y - objectNextPos.y) > STEP_MIN) {
objectNextStepY = max(STEP_MIN, min(STEP_MAX, abs(objectPos.y - objectNextPos.y) / 2));
objectPos.y += (-1) * sign(objectPos.y - objectNextPos.y) * objectNextStepY;
}
} else {
objectPos.x = -1;
objectPos.y = -1;
}
// 在image图像上画一个半径为15的红色圆点
if (nbPixels > 10)
cvDrawCircle(image, objectPos, 10, CV_RGB(255, 0, 0), -1);
/*CvFont* font;
char string[]="i am happy";
cvInitFont(font,CV_FONT_HERSHEY_SIMPLEX,1.0f,1.0f,0,1,8);
cvPutText(image,string,objectPos,font,CV_RGB(0,0,255));
*/
cvShowImage("动态追踪", image);
}
/*
* 功能:得到鼠标点击处的像素值(被跟踪的像素值)
* 输入:event事件,坐标x,y ,标志flags,属性指针param
* 输出:无
*/
void getObjectColor(int event, int x, int y, int flags, void *param = NULL) {
// 定义一个var[4]数组变量pixel
CvScalar pixel;
//定义hsv图像
IplImage *hsv;
//鼠标按下
if(event == CV_EVENT_LBUTTONUP){
// 获取hsv图像
hsv = cvCloneImage(image);
cvCvtColor(image, hsv, CV_BGR2HSV);
// 获取像素值
pixel = cvGet2D(hsv, y, x);
h = (int)pixel.val[0];
s = (int)pixel.val[1];
v = (int)pixel.val[2];
printf("%d\n",hsv->depth);
printf("%d,%d,%d\n",h,s,v);
// 释放image内存
cvReleaseImage(&hsv);
}
}
//修改HSV值
void H_changed(int pos)
{
h=H_slider_pos;
}
void S_changed(int pos)
{
s=S_slider_pos;
}
void V_changed(int pos)
{
v=V_slider_pos;
}
/*****************************************
主程序
******************************************/
int main() {
IplImage *hsv;
CvCapture *capture;
char key=NULL;
int nbPixels;
CvPoint objectNextPos;
// 读取摄像头
capture = cvCreateCameraCapture(1);
// 检测摄像头捕获是否成功
if (!capture) {
printf("Can't initialize the video capture.\n");
return -1;
}
// 创建两个视频窗口
cvNamedWindow("动态追踪", CV_WINDOW_AUTOSIZE);
cvNamedWindow("视频二值化", CV_WINDOW_AUTOSIZE);
cvMoveWindow("动态追踪", 0, 100);
cvMoveWindow("视频二值化", 650, 100);
//创建颜色控制的滚动条
//cvCreateTrackbar("H:","GeckoGeek Mask",&H_slider_pos,255,H_changed);
//cvCreateTrackbar("S:","GeckoGeek Mask",&S_slider_pos,255,S_changed);
//cvCreateTrackbar("V:","GeckoGeek Mask",&V_slider_pos,255,V_changed);
/*
// 点击鼠标选择被跟踪的颜色
cvSetMouseCallback("GeckoGeek Color Tracking", getObjectColor);
*/
/*
//红瓶盖
h=174;
s=146;
v=160;
*/
/*
//红瓶盖
h=171;
s=151;
v=84;
*/
/*
//皮肤
h=11;
s=51;
v=124;
*/
/*
//激光1
h=173;
s=150;//s最大值190,最小值130
v=255;
*/
/*
//激光2
h=173;
s=150;
v=255;
*/
// 按Q退出
while(key != 'Q' && key != 'q') {
// 得到当前图像
image = cvQueryFrame(capture);
// 若无图像,退出当前循环继续获取图像
if(!image)
continue;
//得到被检测的颜色重心
objectNextPos = binarisation(image, &nbPixels);
//添加红色圆点到被检测颜色的重心
addObjectToVideo(image, objectNextPos, nbPixels);
//等待10ms
key = cvWaitKey(10);
}
// 销毁窗口
cvDestroyWindow("动态追踪");
cvDestroyWindow("视频二值化");
// 释放capture资源
cvReleaseCapture(&capture);
return 0;
}