头文件之辩

   前两天整理VC的控件代码,觉得里面有些函数的声明不是很规范,没有很好的模块性,在一个头文件中包含了别的实现文件中的声明,即与某一个实现文件对应的声明,没有存在自己的头文件,而是存在别人的头文件中了,遂就按照这个实践进行整理。

 

 在整理的过程中逐渐地点解了C语言编程,乃至C++编程里面include的组织的“要义”。对于一个模块自身头文件中声明需要引用到头文件,应该声明在自身的头文件中,但实现文件.c或.cpp一般需要引用的文件比自身头文件可能会更多,因为实现文件需要的不仅仅是自己接口的声明,还包含了要实现这些接口实,现体Body需要借用或复用其他模块的接口,而对这些头文件的include,按照当时的顿悟,是不应该在自身的头文件中,而应该在实现文件中进行include。信息是一个逐渐放大过程,纲举目张,在头文件中你见到的只是一个声明或说明,而对于其中实现可能复杂,你不需要可见,也就不需要将这些实现所引用的头文件也放在头文件中,只需要在实现文件中进行include即可。这个声明决定了编译过程给予什么样的地址和空间的安排,在后面再通过链接的过程,将整个源代码生成一个可以执行于某一个平台的程序。感叹,在学校学习时,老师应该将比较低层的东西介绍给学生,而不是只是很粗浅的介绍一个概念,而让学生对这个概念了解不是很透彻。近来常通过维基百科对于一些概念进行深入研究,例如有理数、无理数、代数等,理解了某些基本的东西,就知道这个知识结构里面特征是什么,只所以代数之所为为“代”,呵呵!教育要发展啊。。。。。。。。
 
   按照这样的原则,就粗粗整理了一两个小时,感觉虽然干了一些体力活,但是值得为这点顿悟而付出进一步的劳动,很多时候纸上得来终觉浅,绝知此事要躬行的,在实践中才能领悟的更多。

 

   在整理过程中,遇到了一部分函数的声明出现一些头文件相互包含的场景,才觉得以前的组织方式虽然乱,但至少实现了整个功能的,呵呵!也源于整个代码组织出现问题,但时间太短了,不能进行大的改造,就一部分进行了整理,一部分还按照原来的样子。在一个组织很好的程序里面,很少应该出现反调的情况,绝大多数,应该类似金字塔式,一层层进行支撑,上层需要了解下层,而下层不应该include到上层的东西,不应该出现纠缠,后面再思考这样大的结构吧,先能做多少就做多少,至少会向好的方向发展就可以了,发展本身就是很缓慢的过程,特别是向上的发展,每一步都是不容易,平庸和原地踏步可能是最容易、最省心的!

根据以下c++代码,移植到qt实现opencv摄像头显示#include "QSCamera.h" // API鎻愪緵鐨剆aveData鍑芥暟宸插湪璇ュご鏂囦欢涓0鏄? #include <opencv2/opencv.hpp> #include <iostream> #include <thread> #include <chrono> #include <atomic> #include <fstream> #include <cstring> // 鍏ㄥ眬鍙橀噺瀹氫箟锛堜繚鎸佷笉鍙橈級 std::atomic<bool> exitFlag(false); cv::Mat currentImage; cv::Mat frame; unsigned char* rawSpectralData = nullptr; std::mutex mtx; cv::VideoCapture cap(0); // 璇诲彇.qs鏍煎紡鍏夎氨鏁版嵁锛堜繚鎸佷笉鍙橈紝閫傞厤API淇濆瓨鐨?qs鏂囦欢鏍煎紡锛? cv::Mat readQSData(const std::string& filename) { std::ifstream qsFile(filename, std::ios::binary); if (!qsFile.is_open()) { std::cerr << "閿欒锛氭棤娉曟墦寮€.qs鏂囦欢 " << filename << std::endl; return cv::Mat(); } // 鑾峰彇鏂囦欢澶у皬骞堕獙璇侊紙API淇濆瓨鐨?qs鏂囦欢浠嶄负1600*1200*2瀛楄妭锛? qsFile.seekg(0, std::ios::end); int fileSize = qsFile.tellg(); qsFile.seekg(0, std::ios::beg); const int expectedSize = 1200 * 1600 * 2; if (fileSize != expectedSize) { std::cerr << "璀﹀憡锛?qs鏂囦欢澶у皬涓嶇锛堝疄闄咃細" << fileSize << "锛岄鏈燂細" << expectedSize << "锛? << std::endl; } // 璇诲彇API淇濆瓨鐨勪簩杩涘埗鏁版嵁 unsigned char* data = new unsigned char[expectedSize]; qsFile.read(reinterpret_cast<char*>(data), expectedSize); qsFile.close(); // 杞崲涓篛penCV 16浣嶅崟閫氶亾鐭╅樀锛堟棤棰濆澶勭悊锛岄€傞厤API杈撳嚭鏍煎紡锛? cv::Mat spectralMat(1200, 1600, CV_16UC1, data); cv::Mat result; spectralMat.copyTo(result); delete[] data; return result; } // 鍏夎氨鐩告満鍥炶皟鍑芥暟锛堜繚鎸佷笉鍙橈紝璐熻矗鎺ユ敹鍘熷鏁版嵁骞堕澶勭悊鏄剧ず锛? void callBack(unsigned char* img) { std::lock_guard<std::mutex> lock(mtx); // 缂撳瓨鍘熷鏁版嵁锛屼緵API鐨剆aveData鍑芥暟浣跨敤 rawSpectralData = img; // 澶勭悊16浣嶆暟鎹负8浣嶆樉绀哄浘 cv::Mat image16UC1(1200, 1600, CV_16UC1, img); cv::Mat image8UC1; image16UC1.convertTo(image8UC1, CV_8UC1, 1.0 / 64); currentImage = image8UC1.clone(); } // 鏄剧ず绾跨▼鍑芥暟锛堜繚鎸佷笉鍙橈紝璋冪敤API鐨剆aveData鍑芥暟锛? void displayThreadFunc() { // 鍒涘缓骞惰皟鏁寸獥鍙? cv::namedWindow("Real-time Image", cv::WINDOW_NORMAL); cv::namedWindow("camera", cv::WINDOW_NORMAL); cv::namedWindow("QS Data Preview", cv::WINDOW_NORMAL); cv::resizeWindow("Real-time Image", 320, 240); cv::resizeWindow("camera", 320, 240); cv::resizeWindow("QS Data Preview", 320, 240); int key = 0; static int frameCount = 0; while (!exitFlag) { cv::Mat currentDisplay; unsigned char* currentRawData = nullptr; // 瀹夊叏璇诲彇鍏变韩璧勬簮 { std::lock_guard<std::mutex> lock(mtx); if (!currentImage.empty()) { currentDisplay = currentImage.clone(); } currentRawData = rawSpectralData; } // 鏄剧ず鍥惧儚涓庢寜閿鐞? if (!currentDisplay.empty()) { cv::imshow("Real-time Image", currentDisplay); // 鏅€氱浉鏈哄浘鍍忓鐞? cap >> frame; if (!frame.empty()) { cv::flip(frame, frame, -1); cv::imshow("camera", frame); } key = cv::waitKey(1); if (key == 27) { // ESC閫€鍑? exitFlag = true; } else if (key == 32) { // 绌烘牸閿繚瀛橈紙璋冪敤API鐨剆aveData锛? // 鏋勯€犲熀纭€璺緞锛堜笉鍚悗缂€锛孉PI浼氳嚜鍔ㄦ坊鍔?qs锛? std::string basePath = "/home/lckfb/Desktop/data/QSFrame_" + std::to_string(frameCount); // 1. 淇濆瓨鍏夎氨鏄剧ず鍥撅紙PNG锛? std::string imgFilename = basePath + ".png"; cv::imwrite(imgFilename, currentDisplay); std::cout << "鍏夎氨鍥惧儚淇濆瓨涓?" << imgFilename << std::endl; // 2. 淇濆瓨鏅€氱浉鏈哄浘鍍忥紙PNG锛? std::string vFilename = "/home/lckfb/Desktop/data/VFrame_" + std::to_string(frameCount) + ".png"; cv::imwrite(vFilename, frame); std::cout << "鏅€氬浘鍍忎繚瀛樹负 " << vFilename << std::endl; // 3. 璋冪敤API鎻愪緵鐨剆aveData鍑芥暟淇濆瓨.qs鏂囦欢 if (currentRawData) { // 鐩存帴浼犲師濮嬫暟鎹拰鍩虹璺緞锛孉PI鍐呴儴澶勭悊锛? // - 妫€鏌ユ暟鎹湁鏁堟€? // - 娣诲姞.qs鍚庣紑 // - 浜岃繘鍒跺啓鍏ワ紙绗﹀悎1600*1200*2瀛楄妭鏍煎紡锛? saveData(currentRawData, basePath); } // 4. 棰勮API淇濆瓨鐨?qs鏂囦欢锛堥獙璇佷繚瀛樼粨鏋滐級 std::string qsFilename = basePath + ".qs"; cv::Mat qsData = readQSData(qsFilename); if (!qsData.empty()) { cv::Mat qsPreview; qsData.convertTo(qsPreview, CV_8UC1, 1.0 / 64); cv::imshow("QS Data Preview", qsPreview); } frameCount++; } } else { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } cv::destroyAllWindows(); } int main() { // 鍒濆鍖栧厜璋浉鏈猴紙渚濊禆QSCamera.h鐨凙PI鍑芥暟锛? regeditCallBack(callBack); openCamera("/dev/video9"); // 閰嶇疆鏅€氱浉鏈? cap.set(cv::CAP_PROP_FRAME_WIDTH, 320); cap.set(cv::CAP_PROP_FRAME_HEIGHT, 240); cap.set(cv::CAP_PROP_FPS, 30); if (!cap.isOpened()) { std::cerr << "鏃犳硶鎵撳紑鏅€氱浉鏈猴紒" << std::endl; return -1; } // 鍚姩鏄剧ず绾跨▼ std::thread displayThread(displayThreadFunc); // 鎿嶄綔鎻愮ず std::cout << "鎸塃SC閿€€鍑虹▼搴?..\n"; std::cout << "鎸夌┖鏍奸敭淇濆瓨鍏夎氨鍥惧儚銆佹櫘閫氬浘鍍忓拰.qs鍏夎氨鏁版嵁锛堣皟鐢ˋPI锛?..\n"; // 绛夊緟绾跨▼缁撴潫 displayThread.join(); // 璧勬簮娓呯悊锛堜緷璧朡SCamera.h鐨凙PI鍑芥暟锛? closeCamera(); cap.release(); return 0; }
最新发布
09-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值