Browse Source

v0.1.2 增加棋盘格角点识别接口

chenhongjiang 1 year ago
parent
commit
51079e6714
5 changed files with 236 additions and 5 deletions
  1. 2 1
      ReadMe.txt
  2. 129 0
      chessboard.cpp
  3. 46 0
      chessboard.h
  4. 43 2
      tea_cv_api.cpp
  5. 16 2
      tea_cv_api.h

+ 2 - 1
ReadMe.txt

@@ -1,2 +1,3 @@
 v0.1.0 初始版本,实现整体流程,模型待优化。
-v0.1.1 分开抓取和切割的接口。
+v0.1.1 分开抓取和切割的接口。
+v0.1.2 增加棋盘格角点识别接口。

+ 129 - 0
chessboard.cpp

@@ -0,0 +1,129 @@
+#include <opencv.hpp>
+#include <math.h>
+#include <io.h>
+#include "chessboard.h"
+#include "utils.h"
+
+namespace graft_cv {
+	CChessboard::CChessboard(
+		ConfigParam& cp,
+		CGcvLogger*pLog)
+		:m_cp(cp), 
+		m_pLogger(pLog),
+		m_dtype(img_type::tea_grab)
+	{
+	}
+	CChessboard::~CChessboard() {};
+	int CChessboard::detect(
+		ImgInfo*imginfo, 
+		PositionInfo& posinfo,
+		int corner_row,
+		int corner_col,
+		int x0,
+		int y0,
+		int width,
+		int height,
+		const char* fn)
+	{
+		//1 load data
+		load_data(imginfo, fn);
+
+		//2 
+		if (m_cp.image_show) {
+			cv::Rect rc = cv::Rect(x0, y0, width, height);
+			cv::Mat img_tmp = m_raw_img.clone();
+			cv::rectangle(img_tmp, rc, cv::Scalar(0, 0, 255),3);
+			imshow_wait("crop", img_tmp);			
+		}
+		cv::Mat crop_img = m_raw_img(cv::Range(y0, y0 + height),cv::Range(x0, x0 + width));
+		if (m_cp.image_show) {
+			imshow_wait("cropped", crop_img);
+		}
+		//3 
+		std::vector<cv::Point2f> pointbuf;
+		bool found = cv::findChessboardCorners(
+			crop_img,
+			cv::Size(corner_row, corner_col),
+			pointbuf);
+		if (found){
+			cv::Mat tmp_img = crop_img.clone();
+			if (m_pLogger) {
+				stringstream buff;
+				buff << m_imgId << m_dtype_str << "chessboard corners:\nx\ty\n";
+				for (auto&p : pointbuf) {
+					buff << p.x+x0 << ", " << p.y+y0 << "\n";
+				}
+				m_pLogger->INFO(buff.str());
+			}
+
+			cv::drawChessboardCorners(tmp_img, cv::Size(17, 18), cv::Mat(pointbuf), found);
+			if (m_ppImgSaver && *m_ppImgSaver) {
+				(*m_ppImgSaver)->saveImage(tmp_img, m_imgId + "_rst_0");
+			}
+		}
+		else {
+			if (m_pLogger) {
+				stringstream buff;
+				buff << m_imgId << m_dtype_str << "image, NOT found chessboard corners";
+				m_pLogger->INFO(buff.str());
+			}
+		}
+		return 0;
+	}
+
+	int CChessboard::load_data(
+		ImgInfo*imginfo,
+		const char* fn) {
+		//数据加载功能实现,并生成imageid,保存原始数据到文件
+		int rst = 0;
+		//generate image id
+		if (m_dtype == img_type::tea_grab) {
+			m_imgId = getImgId(img_type::tea_grab);
+			m_dtype_str = string(" tea_grab_chessboard ");
+		}
+		else {
+			m_imgId = getImgId(img_type::tea_cut);
+			m_dtype_str = string(" tea_cut_chessboard ");
+		}
+
+		if (imginfo) {
+			if (m_pLogger) {
+				stringstream buff;
+				buff << m_imgId << m_dtype_str << "image, width=" << imginfo->width
+					<< "\theight=" << imginfo->height;
+				m_pLogger->INFO(buff.str());
+			}
+			if (!isvalid(imginfo)) {
+				if (m_pLogger) {
+					m_pLogger->ERRORINFO(m_imgId + m_dtype_str + "input image invalid.");
+				}
+				throw_msg(m_imgId + " invalid input image");
+
+			}
+			m_raw_img = imginfo2mat(imginfo);
+		}
+		else {
+			cv::Mat img = imread(fn, cv::IMREAD_COLOR);
+			if (img.empty()) {
+				if (m_pLogger) {
+					m_pLogger->ERRORINFO(m_imgId + m_dtype_str + "input image invalid:" + string(fn));
+				}
+				throw_msg(m_imgId + m_dtype_str + "invalid input image: " + string(fn));
+
+			}
+			if (m_pLogger) {
+				stringstream buff;
+				buff << m_imgId << m_dtype_str << "image, width=" << img.cols
+					<< "\theight=" << img.rows;
+				m_pLogger->INFO(buff.str());
+			}
+
+			m_raw_img = img.clone();
+		}
+		//image saver
+		if (m_ppImgSaver && *m_ppImgSaver) {
+			(*m_ppImgSaver)->saveImage(m_raw_img, m_imgId);
+		}
+		return rst;		
+	}
+}

+ 46 - 0
chessboard.h

@@ -0,0 +1,46 @@
+#pragma once
+
+#include <opencv.hpp>
+#include "logger.h"
+#include "data_def.h"
+#include "data_def_api.h"
+#include "imstorage_manager.h"
+
+namespace graft_cv {
+
+
+class CChessboard {
+public:
+	CChessboard(
+		ConfigParam& ap,
+		CGcvLogger*pLog = 0);
+	~CChessboard();
+	void set_image_saver(CImStoreManager** ppis) { m_ppImgSaver = ppis; }
+	int detect(
+		ImgInfo*, 
+		PositionInfo& posinfo,
+		int corner_row,
+		int corner_col,
+		int x0,
+		int y0,
+		int width,
+		int height,
+		const char* fn = 0);
+
+private:
+	img_type m_dtype; // data type: tea_grab, tea_cut
+	string m_imgId;
+	string m_dtype_str;
+	cv::Mat m_raw_img;
+	CImStoreManager** m_ppImgSaver;
+	CGcvLogger* m_pLogger;
+	ConfigParam& m_cp;
+
+	int load_data(
+		ImgInfo*imginfo,
+		const char* fn = 0);
+
+
+};
+
+}

+ 43 - 2
tea_cv_api.cpp

@@ -12,6 +12,7 @@
 #include "utils.h"
 #include "imstorage_manager.h"
 #include "tea_sorter.h"
+#include "chessboard.h"
 
 
 
@@ -20,7 +21,7 @@ extern CRITICAL_SECTION g_cs;
 namespace graft_cv
 {
 
-	char *g_version_str = "0.1.1";
+	char *g_version_str = "0.1.2";
 
 	//configure
 	string g_conf_file = "./tcv_conf.yml";	
@@ -41,7 +42,7 @@ namespace graft_cv
 	//implement	
 	CTeaSort g_tg = CTeaSort(g_cp, img_type::tea_grab, &g_logger);
 	CTeaSort g_tc = CTeaSort(g_cp, img_type::tea_cut, &g_logger);
-	
+	CChessboard g_cb = CChessboard(g_cp, &g_logger);
 
 	//??¶àÏß³ÌÓÐÎÊÌâ
 	map<string, cv::Mat> g_img_cache;
@@ -133,6 +134,7 @@ namespace graft_cv
 		}		
 		g_tg.set_image_saver(&g_pImStore);
 		g_tc.set_image_saver(&g_pImStore);
+		g_cb.set_image_saver(&g_pImStore);
 		return 0;
 	}
 	
@@ -326,6 +328,45 @@ namespace graft_cv
 
 	}
 
+	//13
+	int chessboard_corners(
+		ImgInfo*imginfo,
+		PositionInfo& posinfo,
+		int corner_row,
+		int corner_col,
+		int x0,
+		int y0,
+		int width,
+		int height,
+		const char* fn)
+	{
+		memset(&posinfo, 0, sizeof(PositionInfo));
+		try {			
+			int r = g_cb.detect(imginfo,
+				posinfo,
+				corner_row,
+				corner_col,
+				x0,
+				y0,
+				width,
+				height,
+				fn);
+			return r;
+		}
+		catch (std::exception &err) {
+			g_logger.ERRORINFO(err.what());
+			return 1;
+		}
+		catch (string& msg) {
+			g_logger.ERRORINFO(msg);
+			return 1;
+		}
+		catch (...) {
+			g_logger.ERRORINFO("unknown error");
+			return 1;
+		}
+		return 0;
+	}
 
 
 };

+ 16 - 2
tea_cv_api.h

@@ -83,7 +83,7 @@ namespace graft_cv
 	            // 如果为0,则不存在
 //				posinfo.pp_images;
 //		
-//  返回: 0- 正常; 其他- 失败
+//  返回: 0- 正常,识别到目标; 1- 算法异常失败, -1-没有识别到目标
 	TCV_API int tea_grab_point(ImgInfo*, PositionInfo& posinfo, const char* fn=0);
 	
 	//12 找到切割位置
@@ -108,10 +108,24 @@ namespace graft_cv
 	// 如果为0,则不存在
 	//				posinfo.pp_images;
 	//		
-	//  返回: 0- 正常; 其他- 失败
+	//  返回: 0- 正常,识别到目标; 1- 算法异常失败, -1-没有识别到目标
 	TCV_API int tea_cut_point(ImgInfo*, PositionInfo& posinfo, const char* fn = 0);
 
 
+	//13  
+	// 棋盘格角点识别
+	TCV_API int chessboard_corners(
+		ImgInfo*,				//输入,图像数据
+		PositionInfo& posinfo,	//输出,结果数据,没有用
+		int corner_row,			//输入,棋盘格角点行数
+		int corner_col,			//输入,棋盘格角点列数
+		int x0,					//输入,棋盘格在图像中的左上x
+		int y0,					//输入,棋盘格在图像中的左上y
+		int width,				//输入,棋盘格在图像中的x方向宽度
+		int height,				//输入,棋盘格在图像中的y方向高度
+		const char* fn = 0);	//输入,棋盘格在图像文件,用于测试,默认不用
+
+
 
 };//namespace tea_cv