vs+opencv 完全基于opencv的双目景深与测距的实现

zy18730608243 2016-03-11 05:39:52
加精
代码:
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
//#include <cv.h>
#include <cxmisc.h>
#include <highgui.h>
#include <cvaux.h>
#include <iostream>
#include <ctype.h>
//#include <unistd.h>
#include <stdlib.h>

#include <vector>
#include <string>
#include <algorithm>
#include <ctype.h>
#include <stdarg.h>
#include <string.h>

#include <stdio.h>


using namespace cv;
using namespace std;

//vector<Point2f> point1, point2;
bool left_mouse = false;
Point2f point;
int pic_info[4];
Mat gray, prevGray, image, image1;
const Scalar GREEN = Scalar(0, 255, 0);
int rect_width = 0, rect_height = 0;
Point tmpPoint;
int num = 0;
int m_frameWidth = 640;
int m_frameHeight = 480;
bool m_Calib_Data_Loaded; // 是否成功载入定标参数
cv::Mat m_Calib_Mat_Q; // Q 矩阵
cv::Mat m_Calib_Mat_Remap_X_L; // 左视图畸变校正像素坐标映射矩阵 X
cv::Mat m_Calib_Mat_Remap_Y_L; // 左视图畸变校正像素坐标映射矩阵 Y
cv::Mat m_Calib_Mat_Remap_X_R; // 右视图畸变校正像素坐标映射矩阵 X
cv::Mat m_Calib_Mat_Remap_Y_R; // 右视图畸变校正像素坐标映射矩阵 Y
cv::Mat m_Calib_Mat_Mask_Roi; // 左视图校正后的有效区域
cv::Rect m_Calib_Roi_L; // 左视图校正后的有效区域矩形
cv::Rect m_Calib_Roi_R; // 右视图校正后的有效区域矩形
double m_FL;
//CvStereoBMState *BMState = cvCreateStereoBMState();
int m_numberOfDisparies; // 视差变化范围
cv::StereoBM m_BM;
CvMat* vdisp = cvCreateMat(480, 640, CV_8U);
cv::Mat img1, img2, img1p, img2p, disp, disp8u, pointClouds, imageLeft, imageRight, disparityImage, imaget1;
static IplImage *framet1 = NULL;
static IplImage *framet2 = NULL;
static IplImage *framet3 = NULL;
static IplImage *framet = NULL;


static void onMouse(int event, int x, int y, int /*flags*/, void* /*param*/){


Mat mouse_show;
image.copyTo(mouse_show);

//char buffer[100];
//sprintf(buffer, "D:\\l%d.jpg", num);
//string t1(buffer);

//sprintf(buffer, "D:\\r%d.jpg", num);
//string t(buffer);



if (event == CV_EVENT_LBUTTONDOWN)
{
pic_info[0] = x;
pic_info[1] = y;
cout << "x:" << pic_info[0] << "y:" << pic_info[1] << endl;
left_mouse = true;

//用于存储打印图片
//imwrite(t, image);
// imwrite(t1, image1);
// num = num++;

}
else if (event == CV_EVENT_LBUTTONUP)
{
left_mouse = false;
}
else if ((event == CV_EVENT_MOUSEMOVE) && (left_mouse == true))
{
}
}



int loadCalibData()
{
// 读入摄像头定标参数 Q roi1 roi2 mapx1 mapy1 mapx2 mapy2
try
{
cv::FileStorage fs("calib_paras.xml", cv::FileStorage::READ);
cout << fs.isOpened() << endl;

if (!fs.isOpened())
{
return (0);
}

cv::Size imageSize;
cv::FileNodeIterator it = fs["imageSize"].begin();

it >> imageSize.width >> imageSize.height;
// if (imageSize.width != m_frameWidth || imageSize.height != m_frameHeight) { return (-1); }

vector<int> roiVal1;
vector<int> roiVal2;

fs["leftValidArea"] >> roiVal1;

m_Calib_Roi_L.x = roiVal1[0];
m_Calib_Roi_L.y = roiVal1[1];
m_Calib_Roi_L.width = roiVal1[2];
m_Calib_Roi_L.height = roiVal1[3];

fs["rightValidArea"] >> roiVal2;
m_Calib_Roi_R.x = roiVal2[0];
m_Calib_Roi_R.y = roiVal2[1];
m_Calib_Roi_R.width = roiVal2[2];
m_Calib_Roi_R.height = roiVal2[3];


fs["QMatrix"] >> m_Calib_Mat_Q;
fs["remapX1"] >> m_Calib_Mat_Remap_X_L;
fs["remapY1"] >> m_Calib_Mat_Remap_Y_L;
fs["remapX2"] >> m_Calib_Mat_Remap_X_R;
fs["remapY2"] >> m_Calib_Mat_Remap_Y_R;

cv::Mat lfCamMat;
fs["leftCameraMatrix"] >> lfCamMat;
m_FL = lfCamMat.at<double>(0, 0);

m_Calib_Mat_Q.at<double>(3, 2) = -m_Calib_Mat_Q.at<double>(3, 2);

m_Calib_Mat_Mask_Roi = cv::Mat::zeros(m_frameHeight, m_frameWidth, CV_8UC1);
cv::rectangle(m_Calib_Mat_Mask_Roi, m_Calib_Roi_L, cv::Scalar(255), -1);

m_BM.state->roi1 = m_Calib_Roi_L;
m_BM.state->roi2 = m_Calib_Roi_R;

m_Calib_Data_Loaded = true;

string method;
fs["rectifyMethod"] >> method;
if (method != "BOUGUET")
{
return (-2);
}

}
catch (std::exception& e)
{
m_Calib_Data_Loaded = false;
return (-99);
}

return 1;


}
void updatebm()
{
m_BM.state->preFilterCap = 31;
m_BM.state->SADWindowSize = 19;
m_BM.state->minDisparity = 0;
m_BM.state->numberOfDisparities = 96;
m_BM.state->textureThreshold = 10;
m_BM.state->uniquenessRatio = 25;
m_BM.state->speckleWindowSize = 100;
m_BM.state->speckleRange = 32;

m_BM.state->disp12MaxDiff = -1;

}
int bmMatch(cv::Mat& frameLeft, cv::Mat& frameRight, cv::Mat& disparity, cv::Mat& imageLeft, cv::Mat& imageRight)
{

// 输入检查
if (frameLeft.empty() || frameRight.empty())
{
disparity = cv::Scalar(0);
return 0;
}
if (m_frameWidth == 0 || m_frameHeight == 0)
{
//if (init(frameLeft.cols, frameLeft.rows, "calib_paras.xml"/*待改为由本地设置文件确定*/) == 0) //执行类初始化
// {
return 0;
//}
}

// 转换为灰度图
cv::Mat img1proc, img2proc;
cvtColor(frameLeft, img1proc, CV_BGR2GRAY);
cvtColor(frameRight, img2proc, CV_BGR2GRAY);

// 校正图像,使左右视图行对齐
cv::Mat img1remap, img2remap;
//cout << m_Calib_Data_Loaded << endl;

if (m_Calib_Data_Loaded)
{
remap(img1proc, img1remap, m_Calib_Mat_Remap_X_L, m_Calib_Mat_Remap_Y_L, cv::INTER_LINEAR); // 对用于视差计算的画面进行校正
remap(img2proc, img2remap, m_Calib_Mat_Remap_X_R, m_Calib_Mat_Remap_Y_R, cv::INTER_LINEAR);
}
else
{
img1remap = img1proc;
img2remap = img2proc;
}

// 对左右视图的左边进行边界延拓,以获取与原始视图相同大小的有效视差区域
cv::Mat img1border, img2border;
if (m_numberOfDisparies != m_BM.state->numberOfDisparities)
m_numberOfDisparies = m_BM.state->numberOfDisparities;
copyMakeBorder(img1remap, img1border, 0, 0, m_BM.state->numberOfDisparities, 0, IPL_BORDER_REPLICATE);
copyMakeBorder(img2remap, img2border, 0, 0, m_BM.state->numberOfDisparities, 0, IPL_BORDER_REPLICATE);

// 计算视差
cv::Mat dispBorder;


m_BM(img1border, img2border, dispBorder);
//cvFindStereoCorrespondenceBM(img1border, img2border, dispBorder,BMState);
// 截取与原始画面对应的视差区域(舍去加宽的部分)
cv::Mat disp;
disp = dispBorder.colRange(m_BM.state->numberOfDisparities, img1border.cols);
disp.copyTo(disparity, m_Calib_Mat_Mask_Roi);

//reprojectImageTo3D(dispBorder, pointClouds, m_Calib_Mat_Q, true);

// 输出处理后的图像
//cout << m_Calib_Data_Loaded << endl;
if (m_Calib_Data_Loaded)
{
remap(frameLeft, imageLeft, m_Calib_Mat_Remap_X_L, m_Calib_Mat_Remap_Y_L, cv::INTER_LINEAR);
rectangle(imageLeft, m_Calib_Roi_L, CV_RGB(0, 0, 255), 3);
}

else
frameLeft.copyTo(imageLeft);


if (m_Calib_Data_Loaded)
remap(frameRight, imageRight, m_Calib_Mat_Remap_X_R, m_Calib_Mat_Remap_Y_R, cv::INTER_LINEAR);
else
frameRight.copyTo(imageRight);
rectangle(imageRight, m_Calib_Roi_R, CV_RGB(0, 0, 255), 3);


return 1;
}

int getDisparityImage(cv::Mat& disparity, cv::Mat& disparityImage, bool isColor)
{
// 将原始视差数据的位深转换为 8 位
cv::Mat disp8u;
if (disparity.depth() != CV_8U)
{
if (disparity.depth() == CV_8S)
{
disparity.convertTo(disp8u, CV_8U);
}
else
{
disparity.convertTo(disp8u, CV_8U, 255 / (m_numberOfDisparies*16.));
}
}
else
{
disp8u = disparity;
}

// 转换为伪彩色图像 或 灰度图像
if (isColor)
{
if (disparityImage.empty() || disparityImage.type() != CV_8UC3 || disparityImage.size() != disparity.size())
{
disparityImage = cv::Mat::zeros(disparity.rows, disparity.cols, CV_8UC3);
}

for (int y = 0; y<disparity.rows; y++)
{
for (int x = 0; x<disparity.cols; x++)
{
uchar val = disp8u.at<uchar>(y, x);
uchar r, g, b;

if (val == 0)
r = g = b = 0;
else
{
r = 255 - val;
g = val < 128 ? val * 2 : (uchar)((255 - val) * 2);
b = val;
}

disparityImage.at<cv::Vec3b>(y, x) = cv::Vec3b(r, g, b);

}
}
}
else
{
disp8u.copyTo(disparityImage);
}

return 1;
}

int getPointClouds(cv::Mat& disparity, cv::Mat& pointClouds)
{
if (disparity.empty())
{
return 0;
}

//计算生成三维点云
// cv::reprojectImageTo3D(disparity, pointClouds, m_Calib_Mat_Q, true);

reprojectImageTo3D(disparity, pointClouds, m_Calib_Mat_Q, true);

pointClouds *= 1.6;


for (int y = 0; y < pointClouds.rows; ++y)
{
for (int x = 0; x < pointClouds.cols; ++x)
{
cv::Point3f point = pointClouds.at<cv::Point3f>(y, x);
point.y = -point.y;
pointClouds.at<cv::Point3f>(y, x) = point;
}
}

return 1;
}

void detectDistance(cv::Mat& pointCloud)
{
if (pointCloud.empty())
{
return;
}

// 提取深度图像
vector<cv::Mat> xyzSet;
split(pointCloud, xyzSet);
cv::Mat depth;
xyzSet[2].copyTo(depth);

// 根据深度阈值进行二值化处理
double maxVal = 0, minVal = 0;
cv::Mat depthThresh = cv::Mat::zeros(depth.rows, depth.cols, CV_8UC1);
cv::minMaxLoc(depth, &minVal, &maxVal);
double thrVal = minVal * 1.5;
threshold(depth, depthThresh, thrVal, 255, CV_THRESH_BINARY_INV);
depthThresh.convertTo(depthThresh, CV_8UC1);
//imageDenoising(depthThresh, 3);

double distance = depth.at<float>(pic_info[0], pic_info[1]);
cout << "distance:" << distance << endl;
}











...全文
12007 47 打赏 收藏 转发到动态 举报
写回复
用AI写文章
47 条回复
切换为时间正序
请发表友善的回复…
发表回复
清小欢欢欢 2019-06-11
  • 打赏
  • 举报
回复
reprojectImageTo3D出来的坐标好像不正确,原本应该是1.3m,测出来的是5m,这是为什么。。。求解答。
AllYoung_362 2018-06-27
  • 打赏
  • 举报
回复
引用 41 楼 m0_37927289 的回复:
[quote=引用 21 楼 zy18730608243 的回复:]
[quote=引用 6 楼 hysteric314 的回复:]
那文章我写的...
看你那错误,我猜是你没有把标定的文件放到工程目录下,就是calib_paras.xml这个文件。
对于两个摄像头来说,他们之间参数矩阵只有一个(如果两摄像头间相对位置不变的话),所以定标过程只需要一次即可。既然只需要一次,所以我的程序并没有弄标定的东西(嫌麻烦),而是从外部读取calib_paras.xml这个参数文件,这个文件可以通过大神的代码来进行定标过程然后生成出来。
建议你在用我程序之前先跑一下大神的程序,对大神的代码了解一下。
http://blog.csdn.net/chenyusiyuan/article/details/8131496
以上这些我文章里都写得很清楚了...


我加入了calib_paras.xml这个文件后,能出来x,y坐标,但是 距离怎么出不来?[/quote]
你好,请问一下calib_paras.xml文件应该放在哪里?[/quote]

calib_paras.xml不管放哪都可以,记得把路径写对就行。
比如我的为:cv::FileStorage fs("D:\\***\\***\\***\\calib_paras.xml", cv::FileStorage::READ);
注意绝对路径的格式,写完整
qq_25321991 2018-06-08
  • 打赏
  • 举报
回复
您好我的距离测的只是16000是怎么回事呀
qq_25321991 2018-06-08
  • 打赏
  • 举报
回复
你好,为什么运行后点视差图只有16000这个距离
m0_37927289 2018-03-24
  • 打赏
  • 举报
回复
引用 19 楼 zy18730608243 的回复:
主要是我的电脑opencv 配置太乱了,源码在 https://github.com/yuhuazou/StereoVision 可以下载的。
楼主,您好。我用大神的程序也调出来了,但是在计算视差的时候找不到最近的物体测量距离。请问您在那部分有调试过吗?
m0_37927289 2018-03-24
  • 打赏
  • 举报
回复
引用 19 楼 zy18730608243 的回复:
主要是我的电脑opencv 配置太乱了,源码在 https://github.com/yuhuazou/StereoVision 可以下载的。
楼主,您好。请问您的测距效果怎么样?
m0_37927289 2018-01-30
  • 打赏
  • 举报
回复
引用 21 楼 zy18730608243 的回复:
[quote=引用 6 楼 hysteric314 的回复:] 那文章我写的... 看你那错误,我猜是你没有把标定的文件放到工程目录下,就是calib_paras.xml这个文件。 对于两个摄像头来说,他们之间参数矩阵只有一个(如果两摄像头间相对位置不变的话),所以定标过程只需要一次即可。既然只需要一次,所以我的程序并没有弄标定的东西(嫌麻烦),而是从外部读取calib_paras.xml这个参数文件,这个文件可以通过大神的代码来进行定标过程然后生成出来。 建议你在用我程序之前先跑一下大神的程序,对大神的代码了解一下。 http://blog.csdn.net/chenyusiyuan/article/details/8131496 以上这些我文章里都写得很清楚了...
我加入了calib_paras.xml这个文件后,能出来x,y坐标,但是 距离怎么出不来?[/quote] 你好,请问一下calib_paras.xml文件应该放在哪里?
qq_27125783 2016-12-11
  • 打赏
  • 举报
回复
急求camera_params.xml文件以及对应相机拍摄的图片 啊,能不能有人给我发一份?感激不尽!!!1365852721@qq.com
码农小程 2016-11-29
  • 打赏
  • 举报
回复
引用 19 楼 zy18730608243 的回复:
主要是我的电脑opencv 配置太乱了,源码在 https://github.com/yuhuazou/StereoVision 可以下载的。
层主,你的测距效果怎么样?
码农小程 2016-11-29
  • 打赏
  • 举报
回复
引用 12 楼 zy18730608243 的回复:
终于调出来了。
测距结果咋样?
Dashawn_Tang 2016-11-22
  • 打赏
  • 举报
回复
你好 我能看一下生成的calib_paras.xml文件结构吗 我运行大神的代码在按照你说的依旧报错 我想用matlab得到的标定参数填入xml文件中 再泡你的代码
等待的根号三 2016-08-04
  • 打赏
  • 举报
回复
引用 6 楼 hysteric314 的回复:
那文章我写的... 看你那错误,我猜是你没有把标定的文件放到工程目录下,就是calib_paras.xml这个文件。 对于两个摄像头来说,他们之间参数矩阵只有一个(如果两摄像头间相对位置不变的话),所以定标过程只需要一次即可。既然只需要一次,所以我的程序并没有弄标定的东西(嫌麻烦),而是从外部读取calib_paras.xml这个参数文件,这个文件可以通过大神的代码来进行定标过程然后生成出来。 建议你在用我程序之前先跑一下大神的程序,对大神的代码了解一下。 http://blog.csdn.net/chenyusiyuan/article/details/8131496 以上这些我文章里都写得很清楚了...
如何对多个障碍物进行距离检测呢?求大神指导啊
等待的根号三 2016-08-04
  • 打赏
  • 举报
回复
引用 32 楼 qq_20840409 的回复:
楼主代码有bug,在distance = depth.at<float>(pic_info[0], pic_info[1]);处,应该是y值在前,x值在后,可以尝试一下,效果图如下,误差会缩小在8%左右,最近在进行双目测距,想把它利用在无人机、小车上,求研友。。。
你好,你这显示的数据全部是距离信息吗?使用两张已经拍好的图片吗?求指导啊
qq_26009765 2016-07-30
  • 打赏
  • 举报
回复
您好,我想问一下你测得距离准吗,好像就是一个值16000,然后就是得到双目标定结果后,显示标定结果出现异常,这两个问题让我头疼了很久,求解释。谢谢您的回答
qq_24722143 2016-07-04
  • 打赏
  • 举报
回复
这里的距离是什么的距离啊?可以测量任意物体的某一尺寸距离吗?比如泡面杯的高度,热水瓶的高度、宽度?
  • 打赏
  • 举报
回复

楼主代码有bug,在distance = depth.at<float>(pic_info[0], pic_info[1]);处,应该是y值在前,x值在后,可以尝试一下,效果图如下,误差会缩小在8%左右,最近在进行双目测距,想把它利用在无人机、小车上,求研友。。。
pww71 2016-05-08
  • 打赏
  • 举报
回复
http://download.csdn.net/index.php/mobile/source/detail/pww71/9513746
素事 2016-05-05
  • 打赏
  • 举报
回复
最近这么多双目测距是什么情况
赵4老师 2016-05-04
  • 打赏
  • 举报
回复
期待楼主使用我的“倚天剑”斩获妖孽之后,将你的成果连同测试用图片打包给我邮箱发一份。
zy18730608243 2016-05-03
  • 打赏
  • 举报
回复
引用 27 楼 zhao4zhong1 的回复:
是该祭出“倚天剑”的时候了! 有时不将“调用函数名字+各参数值,进入函数后各参数值,中间变量值,退出函数前准备返回的值,返回函数到调用处后函数名字+各参数值+返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的,包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行! 写日志到文件参考下面:
//循环向a函数每次发送200个字节长度(这个是固定的)的buffer,
//a函数中需要将循环传进来的buffer,组成240字节(也是固定的)的新buffer进行处理,
//在处理的时候每次从新buffer中取两个字节打印
#ifdef _MSC_VER
    #pragma warning(disable:4996)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
    #include <windows.h>
    #include <process.h>
    #include <io.h>
    #define  MYVOID             void
    #define  vsnprintf          _vsnprintf
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  MYVOID             void *
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef _MSC_VER
void Lock(CRITICAL_SECTION *l) {
    EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
    LeaveCriticalSection(l);
}
void sleep_ms(int ms) {
    Sleep(ms);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
void sleep_ms(int ms) {
    usleep(ms*1000);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
    struct tm *now;
    struct timeb tb;

    if (NULL==pszFmt||0==pszFmt[0]) return;
    vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,logstr);
    flog=fopen(logfilename1,"a");
    if (NULL!=flog) {
        fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
        if (ftell(flog)>MAXLOGSIZE) {
            fclose(flog);
            if (rename(logfilename1,logfilename2)) {
                remove(logfilename2);
                rename(logfilename1,logfilename2);
            }
        } else {
            fclose(flog);
        }
    }
}
void Log(const char *pszFmt,...) {
    va_list argp;

    Lock(&cs_log);
    va_start(argp,pszFmt);
    LogV(pszFmt,argp);
    va_end(argp);
    Unlock(&cs_log);
}
//Log}
#define ASIZE    200
#define BSIZE    240
#define CSIZE      2
char Abuf[ASIZE];
char Cbuf[CSIZE];
CRITICAL_SECTION cs_HEX ;
CRITICAL_SECTION cs_BBB ;
struct FIFO_BUFFER {
    int  head;
    int  tail;
    int  size;
    char data[BSIZE];
} BBB;
int No_Loop=0;
void HexDump(int cn,char *buf,int len) {
    int i,j,k;
    char binstr[80];

    Lock(&cs_HEX);
    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%03d %04x -",cn,i);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            Log("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        Log("%s\n",binstr);
    }
    Unlock(&cs_HEX);
}
int GetFromRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {
    int lent,len1,len2;

    lent=0;
    Lock(cs);
    if (fbuf->size>=len) {
        lent=len;
        if (fbuf->head+lent>BSIZE) {
            len1=BSIZE-fbuf->head;
            memcpy(buf     ,fbuf->data+fbuf->head,len1);
            len2=lent-len1;
            memcpy(buf+len1,fbuf->data           ,len2);
            fbuf->head=len2;
        } else {
            memcpy(buf     ,fbuf->data+fbuf->head,lent);
            fbuf->head+=lent;
        }
        fbuf->size-=lent;
    }
    Unlock(cs);
    return lent;
}
MYVOID thdB(void *pcn) {
    char        *recv_buf;
    int          recv_nbytes;
    int          cn;
    int          wc;
    int          pb;

    cn=(int)pcn;
    Log("%03d thdB              thread begin...\n",cn);
    while (1) {
        sleep_ms(10);
        recv_buf=(char *)Cbuf;
        recv_nbytes=CSIZE;
        wc=0;
        while (1) {
            pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);
            if (pb) {
                Log("%03d recv %d bytes\n",cn,pb);
                HexDump(cn,recv_buf,pb);
                sleep_ms(1);
            } else {
                sleep_ms(1000);
            }
            if (No_Loop) break;//
            wc++;
            if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
        }
        if (No_Loop) break;//
    }
#ifndef _MSC_VER
    pthread_exit(NULL);
#endif
}
int PutToRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {
    int lent,len1,len2;

    Lock(cs);
    lent=len;
    if (fbuf->size+lent>BSIZE) {
        lent=BSIZE-fbuf->size;
    }
    if (fbuf->tail+lent>BSIZE) {
        len1=BSIZE-fbuf->tail;
        memcpy(fbuf->data+fbuf->tail,buf     ,len1);
        len2=lent-len1;
        memcpy(fbuf->data           ,buf+len1,len2);
        fbuf->tail=len2;
    } else {
        memcpy(fbuf->data+fbuf->tail,buf     ,lent);
        fbuf->tail+=lent;
    }
    fbuf->size+=lent;
    Unlock(cs);
    return lent;
}
MYVOID thdA(void *pcn) {
    char        *send_buf;
    int          send_nbytes;
    int          cn;
    int          wc;
    int           a;
    int          pa;

    cn=(int)pcn;
    Log("%03d thdA              thread begin...\n",cn);
    a=0;
    while (1) {
        sleep_ms(100);
        memset(Abuf,a,ASIZE);
        a=(a+1)%256;
        if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop
        send_buf=(char *)Abuf;
        send_nbytes=ASIZE;
        Log("%03d sending %d bytes\n",cn,send_nbytes);
        HexDump(cn,send_buf,send_nbytes);
        wc=0;
        while (1) {
            pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);
            Log("%03d sent %d bytes\n",cn,pa);
            HexDump(cn,send_buf,pa);
            send_buf+=pa;
            send_nbytes-=pa;
            if (send_nbytes<=0) break;//
            sleep_ms(1000);
            if (No_Loop) break;//
            wc++;
            if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
        }
        if (No_Loop) break;//
    }
#ifndef _MSC_VER
    pthread_exit(NULL);
#endif
}
int main() {
#ifdef _MSC_VER
    InitializeCriticalSection(&cs_log);
    InitializeCriticalSection(&cs_HEX );
    InitializeCriticalSection(&cs_BBB );
#else
    pthread_t threads[2];
    int threadsN;
    int rc;
    pthread_mutex_init(&cs_log,NULL);
    pthread_mutex_init(&cs_HEX,NULL);
    pthread_mutex_init(&cs_BBB,NULL);
#endif
    Log("Start===========================================================\n");

    BBB.head=0;
    BBB.tail=0;
    BBB.size=0;

#ifdef _MSC_VER
    _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);
    _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2);
#else
    threadsN=0;
    rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
    rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
#endif

    if (!access("No_Loop",0)) {
        remove("No_Loop");
        if (!access("No_Loop",0)) {
            No_Loop=1;
        }
    }
    while (1) {
        sleep_ms(1000);
        if (No_Loop) break;//
        if (!access("No_Loop",0)) {
            No_Loop=1;
        }
    }
    sleep_ms(3000);
    Log("End=============================================================\n");
#ifdef _MSC_VER
    DeleteCriticalSection(&cs_BBB );
    DeleteCriticalSection(&cs_HEX );
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_BBB);
    pthread_mutex_destroy(&cs_HEX);
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}
不错,是个好办法!
加载更多回复(27)

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧