OpenCV中的onMouse事件、ROI区域设置、直线斜率检测

//crop:probe1.bmp source:canny_probe.jpg


#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>


static int  otsu(IplImage* A, IplImage* B,const int width,const int height);
static void Controus(IplImage* pImg,IplImage* pContourImg,int* total1,int* total2);
static void GetSlope(int total1,int total2,const int width,const int height);
void onMouse(int event,int x,int y,int flags,void *);
//********************************************
CvPoint prev_pt={-1,-1} ;  
CvPoint pt_beg={-1,-1},pt_end = {-1,-1};   
IplImage *tmp = NULL;
IplImage* pSrcResize = NULL;
//********************************************


int main( int argc, char** argv )
{     
IplImage *src = NULL; 
IplImage* pSrc = NULL;
IplImage* pContourImg = NULL;
IplImage *dst = NULL;  
int c = 0; 
int total1 = 0,total2 = 0;
int width  = 0;
int height = 0;
CvRect rect1,rect2;
  
if( argc >= 2 && (src = cvLoadImage( argv[1], 0)) != 0)
{
//load src and show it
cvNamedWindow("SRC",1);
cvShowImage("SRC",src); 
pSrcResize = cvCreateImage(cvSize(src->width,src->height),src->depth,src->nChannels);


//Get src's ROI and resize it to the resize it to pSrcResize as src's size
rect2.x = 280;
rect2.y = 110;
rect2.width = 240;
rect2.height = 180;
cvSetImageROI(src,rect2);
cvResize(src,pSrcResize);
cvNamedWindow("Resource", CV_WINDOW_AUTOSIZE);
cvShowImage("Resource",pSrcResize);
cvResetImageROI(src);


//mouse event
tmp = cvCloneImage(pSrcResize); 
cvSetMouseCallback("Resource",onMouse ,0);


for (;;)  
{   
c = cvWaitKey(10);  
if ((char)c==13)  //beat enter to get ROI area
{  
if (pt_beg.x!=-1)  
{  
//Get pSrcResize's ROI as object
rect1.x = min(pt_beg.x,pt_end.x);  
rect1.y = min(pt_beg.y,pt_end.y);  
rect1.height = abs(pt_end.y-pt_beg.y);  
rect1.width = abs(pt_end.x-pt_beg.x);  
cvSetImageROI(pSrcResize,rect1);  
dst = cvCreateImage(cvSize(rect1.width,rect1.height),pSrcResize->depth,pSrcResize->nChannels);  
dst = cvCloneImage(pSrcResize); 
cvResetImageROI(src);
cvNamedWindow("Selected",1); 
cvShowImage("Selected",dst);
//cvSaveImage("selected.jpg",dst); 


printf("RECT1:rect1.x=%d,rect1.y=%d\n",rect1.x,rect1.y);
printf("RECT1:height=%d,width=%d\n",rect1.height,rect1.width); 
printf("ROI:Height=%d,Width=%d.\n",pSrcResize->roi->height,pSrcResize->roi->width); 
//printf("DST Height=%d,Width=%d\n",dst->height,dst->width);  

//Copy dst to pSrc,whether it is need or not,at present,the step is need
cvNamedWindow("Bw",1);    
pSrc = cvCreateImage(cvSize(rect1.width,rect1.height),dst->depth,dst->nChannels);
pSrc = cvCloneImage(dst);  
width  = pSrc->width;
height = pSrc->height;
otsu(pSrc,pSrc,width,height);
cvShowImage( "Bw", pSrc);


Controus(pSrc,pContourImg,&total1,&total2);
GetSlope(total1,total2,rect1.width,rect1.height);

cvReleaseImage( &src );
cvDestroyWindow( "SRC" );
cvReleaseImage(&pSrcResize);
cvDestroyWindow( "Resource" );
cvReleaseImage(&dst);
cvDestroyWindow("Selected");
cvReleaseImage( &pSrc );
cvDestroyWindow("Bw");
cvReleaseImage( &pContourImg );
cvDestroyWindow( "contour" );
cvDestroyWindow( "Canny" );
break;  
}  
}  
else if ((char)c==27) //if beat enter,then exit  
{  
cvReleaseImage(&tmp);  
cvReleaseImage(&src);  
cvDestroyWindow("SRC"); 
cvDestroyWindow( "Resource" );
break;  
}  
}
}
else //if input parameter is wrong ,release relative resource
{
cvReleaseImage(&pContourImg);
cvDestroyWindow("contour");
cvReleaseImage(&pSrcResize);
cvDestroyWindow("Resource");
cvReleaseImage(&src);  
cvDestroyWindow("SRC");
cvReleaseImage(&pSrc);
cvDestroyWindow("Canny");
return -1;
}

return 0;
}


/***********************************************************************************************
static void Controus(IplImage* pImg,int toatl1,int total2)
Function:Do morphologic operations and find contours use cvFindControus arithmetic
input parameter:
IplImage* source:source image
int* total1:number of points of first(down) controus
int* total2:number of points of second(up) controus
output parameter:
None
Date:2013.04.23
Author:LiuYaqiang
*************************************************************************************************/
static void Controus(IplImage* pImg,IplImage* pContourImg,int* total1,int* total2)
{
int Nc=0,Th=0,i=0;
FILE *fp1=NULL;
FILE *fp2=NULL;
CvSeq* contour  = {0};
int mode = CV_RETR_LIST;//CV_RETR_LIST EXTERNAL
int method = CV_CHAIN_APPROX_SIMPLE;
CvMemStorage* storage = cvCreateMemStorage(0);
pContourImg = cvCreateImage(cvGetSize(pImg),
 IPL_DEPTH_8U,
 3);


cvNamedWindow("Canny", 1);
cvNamedWindow("contour",1);
cvCanny(pImg, pImg, 0.2, 0.8, 3);
cvShowImage("Canny", pImg);
//**********************************************
//cvSmooth( pImg, pImg, CV_GAUSSIAN, 3, 0 );
//Th = otsu(pImg,pImg,pImg->width,pImg->height);
//**********************************************
cvCvtColor(pImg, pContourImg, CV_GRAY2BGR);
Nc=cvFindContours( pImg, storage, &contour, sizeof(CvContour),mode, method);
fp1=fopen("data1.txt","w");
fp2=fopen("data2.txt","w");
cout<<"width="<<pImg->width<<" height="<<pImg->height<<endl;


//for (;contour!=0;contour=contour->h_next)
for(i=0;i<contour->total;i++)
{
CvPoint* p=(CvPoint*)cvGetSeqElem(contour,i);
//fwrite(buf,sizeof(buf),1,fp);
//cout<<"(p->x,p->y)\t"<<"("<<p->x<<","<<p->y<<")"<<endl;
fprintf(fp1,"%d %d\n",p->x,p->y);
}
cout<<"contour->total="<<contour->total<<endl;
*total1 = contour->total;
cvDrawContours(pContourImg, contour,CV_RGB(255,0,0), CV_RGB(0, 255, 0),0, 1, 0,cvPoint(0,0));


contour=contour->h_next;
*total2 = contour->total;
for(i=0;i<contour->total;i++)
{
CvPoint* p=(CvPoint*)cvGetSeqElem(contour,i);
//fwrite(buf,sizeof(buf),1,fp);
//cout<<"(p->x,p->y)\t"<<"("<<p->x<<","<<p->y<<")"<<endl;
fprintf(fp2,"%d %d\n",p->x,p->y);
}
cout<<"contour->h_next->total="<<contour->total<<endl;
cvDrawContours(pContourImg, contour,CV_RGB(255,0,0), CV_RGB(0, 255, 0),0, 1, 0,cvPoint(0,0));


cout<<"Nc="<<Nc<<endl;
cvShowImage( "contour", pContourImg );
cvReleaseMemStorage(&storage);

fclose(fp1);
fclose(fp2);
}


/***********************************************************************
static void GetSlope(int total1,int total2,const int width,const int height)
Function:Get slope of lines
input parameter:
int total1:number of points of down line
int total2:number of points of up line
int width  :width of source image
int height :height of source image
output parameter:
int T:value of AdaptiveThreshold
Date:2013.04.23
Author:LiuYaqiang
***********************************************************************/
static void GetSlope(int total1,int total2,const int width,const int height)
{
FILE* fp3 = NULL;
FILE* fp4 = NULL;
//FILE* fp5 = NULL;
int a = 0,b = 0,c = 0,d = 0,i = 0;
fp3 = fopen("data1.txt","r");
fp4 = fopen("data2.txt","r");
//fp5 = fopen("data3.txt","a");
IplImage* img = cvCreateImage(cvSize(width,height),8,3);
cvNamedWindow("fitline", CV_WINDOW_AUTOSIZE);
CvPoint* points1 = (CvPoint*)malloc(total1 * sizeof(CvPoint));
CvPoint* points2 = (CvPoint*)malloc(total2 * sizeof(CvPoint));
CvMat pointMat = cvMat(1, total1, CV_32SC2, points1);
CvMat pointMat1 = cvMat(1, total2, CV_32SC2, points2);
CvPoint pt1, pt2;
float line[4] = {0};
float dd = 0.0,t = 0.0;
float k1 = 0.0,k2 = 0.0;


for(i=0;i<total1;i++)
{
fscanf(fp3,"%d %d",&a,&b);
points1[i].x = a;
        points1[i].y = b;
//printf("a=%d,b=%d\n",a,b);
}


cvFitLine( &pointMat, CV_DIST_L2, 0, 0.01, 0.01, line );
    cvZero( img );
dd = (float)sqrt((double)line[0]*line[0] + (double)line[1]*line[1]);
    line[0] /= dd;
    line[1] /= dd;
printf("**************************************\n");
printf("line[0]=%f,line[1]=%f\n",line[0],line[1]);
printf("line[2]=%f,line[3]=%f\n",line[2],line[3]);
    t = (float)(img->width + img->height);
    pt1.x = cvRound(line[2] - line[0]*t);
    pt1.y = cvRound(line[3] - line[1]*t);    //img->height-
pt2.x = cvRound(line[2] + line[0]*t);
    pt2.y = cvRound(line[3] + line[1]*t);
cvLine( img, pt1, pt2, CV_RGB(255,0,0), 1, CV_AA, 0 );



//calculate slope
printf("pt1.x=%d,pt1.y=%d\n",pt1.x,pt1.y);
printf("pt2.x=%d,pt2.y=%d\n",pt2.x,pt2.y);
k1=(float)(pt2.y-pt1.y)/(pt2.x-pt1.x);
printf("k1=%f\n",k1); 
//fprintf(fp5,"%f ",k1);


printf("**************************************\n");
for(i=0;i<total2;i++)
{
fscanf(fp4,"%d %d",&c,&d);
points2[i].x = c;
        points2[i].y = d;
}
cvFitLine( &pointMat1, CV_DIST_L2, 0, 0.01, 0.01, line );
printf("line[0]=%f,line[1]=%f\n",line[0],line[1]);
printf("line[2]=%f,line[3]=%f\n",line[2],line[3]);
    t = (float)(img->width + img->height);
    pt1.x = cvRound(line[2] - line[0]*t);
    pt1.y = cvRound(line[3] - line[1]*t);    //img->height-
pt2.x = cvRound(line[2] + line[0]*t);
    pt2.y = cvRound(line[3] + line[1]*t);


cvLine( img, pt1, pt2, CV_RGB(255,0,0), 1, CV_AA, 0 );
printf("pt1.x=%d,pt1.y=%d\n",pt1.x,pt1.y);
printf("pt2.x=%d,pt2.y=%d\n",pt2.x,pt2.y);
k2=(float)(pt2.y-pt1.y)/(pt2.x-pt1.x);
printf("k2=%f\n",k2); 
//fprintf(fp5,"%f\n",k2);


cvShowImage( "fitline", img );
cvWaitKey(0);


free(points1);
free(points2);
cvReleaseImage(&img);
cvDestroyWindow("fitline");
fclose(fp3);
fclose(fp4);
//fclose(fp5);
}
 


/***********************************************************************
static int otsu(IplImage* A, IplImage* B,const int width,const int height)
Function:get AdaptiveThreshold
input parameter:
IplImage* A:source image
IplImage* B:output image
int width  :width of source image
int height :height of source image
output parameter:
int T:value of AdaptiveThreshold
Date:2013.04.23
Author:LiuYaqiang
***********************************************************************/
static int otsu(IplImage* A, IplImage* B,const int width,const int height)
{
long int N = height * width;
int i = 0,T = 0;
int    h[256] = {0};
double p[256] = {0};
double u[256] = {0};
double w[256] = {0};
double uT = 0.0,sigma2fang = 0.0;
double sigma2fang_max = -10000;


//calculate histogram
for(i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
for(int k = 0; k < 256; k++)
{
if(((uchar*)(A->imageData + A->widthStep*i))[j] == k)
h[k]++;
}
}


//calculate ratio of every bin 
    for(i = 0; i < 256; i++)
{
p[i] = h[i] / double(N);
}       


for(int k = 0; k < 256; k++)
{
uT = 0;


for(i = 0; i <= k; i++)
{
w[k] += p[i];
u[k] += i*p[i];
}


for(i = 0; i < 256; i++)
{
uT += i*p[i];
}


sigma2fang = (uT*w[k] - u[k])*(uT*w[k] - u[k]) / (w[k]*(1-w[k]));


if(sigma2fang > sigma2fang_max)
{
sigma2fang_max = sigma2fang;
T = k;
}
}
 
for(i = 0; i < height; i++)   
{
for(int j = 0; j < width; j++)
{
if(((uchar*)(A->imageData + A->widthStep*i))[j] > T)
{
((uchar*)(B->imageData + B->widthStep*i))[j] = 255;
}
else
{
((uchar*)(B->imageData + B->widthStep*i))[j] = 0;
}
}
}
return T;
}


/***********************************************************************
void onMouse(int event,int x,int y,int flags,void *)  
Function:get ROI area
input parameter:
int event:current mouse event
int x:current x coordinate
int y:current y coordinate
int flags:
void *
output parameter:
None
Date:2013.04.25
Author:LiuYaqiang
***********************************************************************/
void onMouse(int event,int x,int y,int flags,void *)  
{  
//printf("x=%d,y=%d./n",x,y);  
//printf("Begin:x=%d,y=%d./n",pt_beg.x,pt_beg,y);  
//printf("END:x=%d,y=%d./n",pt_end.x,pt_end.y);  
IplImage* color = NULL;
CvPoint pt1={-1,-1},pt2={-1,-1};  


if (!tmp)  
{  
return ;  
}  
else
{
color = cvCreateImage(cvGetSize(tmp),tmp->depth,3); 
}
  
/*判断左键是否放开,并且没有进行拖拽*/  
if (event == CV_EVENT_LBUTTONUP||!(flags & CV_EVENT_FLAG_LBUTTON))  
{//CV_EVENT_LBUTTONUP左键放开,CV_EVENT_FLAG_LBUTTON左键拖拽,  
prev_pt=cvPoint(-1,-1);  
}  
  
/*若左键按下则记录为起始点*/  
else if (event == CV_EVENT_LBUTTONDOWN)  
{  
prev_pt = cvPoint(x,y);  
pt_beg = cvPoint(x,y);  
}  
  
/*若鼠标在滑动,并且在拖拽状态*/  
else if (event == CV_EVENT_MOUSEMOVE && (flags && CV_EVENT_FLAG_LBUTTON) )  
{  
cvCopy(pSrcResize,tmp);  
CvPoint pt =cvPoint(x,y);
cvCvtColor(tmp,color,CV_GRAY2BGR);
  
/*得到另外两个点,以便进行矩形拖动绘制*/  
pt1.x = pt.x;  
pt1.y = prev_pt.y;  
pt2.x = prev_pt.x;  
pt2.y = pt.y;  
  
cvLine( color, prev_pt, pt1, CV_RGB(255,0,0), 1, 8, 0 );  //cvScalarAll(255) CV_RGB(255,0,0)
cvLine( color, prev_pt, pt2, CV_RGB(255,0,0), 1, 8, 0 );  
cvLine( color, pt1, pt, CV_RGB(255,0,0), 1, 8, 0 );  
cvLine( color, pt2, pt, CV_RGB(255,0,0), 1, 8, 0 );  
  
pt_end = pt;  
cvShowImage("Resource",color);  
}  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值