huago-corrcet_tools/HuaGoCorrect/m_Dis.cpp

554 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// m_Dis.cpp: 实现文件
//
#include "stdafx.h"
#include "HuaGoCorrect.h"
#include "m_Dis.h"
#include "afxdialogex.h"
#include "filetools.h"
#include "Config.h"
// m_Dis 对话框
IMPLEMENT_DYNAMIC(m_Dis, CDialog)
m_Dis::m_Dis(CWnd* pParent /*=nullptr*/)
: CDialog(IDD_DIS_DIALOG1, pParent),
d_canget(false),
d_run(false),
m_iQA(0)
{
d_run = true;
d_thred = std::thread(&m_Dis::distortion, this);
}
m_Dis::~m_Dis()
{
if (d_thred.joinable())
{
d_run = false;
d_thred.join();
}
}
void m_Dis::SetEnableGetImage(bool enable)
{
d_canget = enable;
}
int iPic = 0;
int m_QA_num = 0;
void m_Dis::distortion()
{
while (d_run)
{
if (d_canget)
{
if (d_drv)
{
if (!d_drv->Get_IsImageQueueEmpty())
{
cv::Mat mat;
d_drv->aquire_image(mat);
if (!mat.empty())
{
iPic++;
curve(mat, iPic, d_distortonoaram);
}
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void m_Dis::setgcn_drv(GScn_Drv * drv)
{
if ( d_drv!= drv)
d_drv = drv;
}
void m_Dis::updatadistorionparam()
{
CString str_edit[6], str_text[6];
GetDlgItem(IDC_EDIT2)->GetWindowText(str_edit[0]);
GetDlgItem(IDC_EDIT5)->GetWindowText(str_edit[1]);
GetDlgItem(IDC_EDIT8)->GetWindowText(str_edit[2]);
GetDlgItem(IDC_EDIT11)->GetWindowText(str_edit[3]);
GetDlgItem(IDC_EDIT14)->GetWindowText(str_edit[4]);
GetDlgItem(IDC_EDIT17)->GetWindowText(str_edit[5]);
GetDlgItem(IDC_EDIT3)->GetWindowText(str_text[0]);
GetDlgItem(IDC_EDIT6)->GetWindowText(str_text[1]);
GetDlgItem(IDC_EDIT9)->GetWindowText(str_text[2]);
GetDlgItem(IDC_EDIT12)->GetWindowText(str_text[3]);
GetDlgItem(IDC_EDIT15)->GetWindowText(str_text[4]);
GetDlgItem(IDC_EDIT18)->GetWindowText(str_text[5]);
::WritePrivateProfileString(_T("ObjValue"), _T("objvalue_x1"), _T(str_edit[0]), INI_FILE_NAME);
::WritePrivateProfileString(_T("ObjValue"), _T("objvalue_y1"), _T(str_edit[1]), INI_FILE_NAME);
::WritePrivateProfileString(_T("ObjValue"), _T("objvalue_x2"), _T(str_edit[2]), INI_FILE_NAME);
::WritePrivateProfileString(_T("ObjValue"), _T("objvalue_y2"), _T(str_edit[3]), INI_FILE_NAME);
::WritePrivateProfileString(_T("ObjValue"), _T("objvalue_x3"), _T(str_edit[4]), INI_FILE_NAME);
::WritePrivateProfileString(_T("ObjValue"), _T("objvalue_y3"), _T(str_edit[5]), INI_FILE_NAME);
::WritePrivateProfileString(_T("LimitOffset"), _T("limitoffset_x1"), _T(str_text[0]), INI_FILE_NAME);
::WritePrivateProfileString(_T("LimitOffset"), _T("limitoffset_y1"), _T(str_text[1]), INI_FILE_NAME);
::WritePrivateProfileString(_T("LimitOffset"), _T("limitoffset_x2"), _T(str_text[2]), INI_FILE_NAME);
::WritePrivateProfileString(_T("LimitOffset"), _T("limitoffset_y2"), _T(str_text[3]), INI_FILE_NAME);
::WritePrivateProfileString(_T("LimitOffset"), _T("limitoffset_x3"), _T(str_text[4]), INI_FILE_NAME);
::WritePrivateProfileString(_T("LimitOffset"), _T("limitoffset_y3"), _T(str_text[5]), INI_FILE_NAME);
for (int j = 0; j < 6; j++)
{
str_edit[j].ReleaseBuffer();
str_text[j].ReleaseBuffer();
}
d_distortonoaram = getdistorionparam();
}
DISTORTIONPARAMS m_Dis::getdistorionparam()
{
DISTORTIONPARAMS dis_config ;
CString str;
dis_config.LimitOffset[0] = ::GetPrivateProfileInt(_T("LimitOffset"), _T("limitoffset_x1"), 0, INI_FILE_NAME);
dis_config.LimitOffset[1] = ::GetPrivateProfileInt(_T("LimitOffset"), _T("limitoffset_y1"), 0, INI_FILE_NAME);
dis_config.LimitOffset[2] = ::GetPrivateProfileInt(_T("LimitOffset"), _T("limitoffset_x2"), 0, INI_FILE_NAME);
dis_config.LimitOffset[3] = ::GetPrivateProfileInt(_T("LimitOffset"), _T("limitoffset_y2"), 0, INI_FILE_NAME);
dis_config.LimitOffset[4] = ::GetPrivateProfileInt(_T("LimitOffset"), _T("limitoffset_x3"), 0, INI_FILE_NAME);
dis_config.LimitOffset[5] = ::GetPrivateProfileInt(_T("LimitOffset"), _T("limitoffset_y3"), 0, INI_FILE_NAME);
dis_config.ObjValues[0] = ::GetPrivateProfileInt(_T("ObjValue"), _T("objvalue_x1"), 0, INI_FILE_NAME);
dis_config.ObjValues[1] = ::GetPrivateProfileInt(_T("ObjValue"), _T("objvalue_y1"), 0, INI_FILE_NAME);
dis_config.ObjValues[2] = ::GetPrivateProfileInt(_T("ObjValue"), _T("objvalue_x2"), 0, INI_FILE_NAME);
dis_config.ObjValues[3] = ::GetPrivateProfileInt(_T("ObjValue"), _T("objvalue_y2"), 0, INI_FILE_NAME);
dis_config.ObjValues[4] = ::GetPrivateProfileInt(_T("ObjValue"), _T("objvalue_x3"), 0, INI_FILE_NAME);
dis_config.ObjValues[5] = ::GetPrivateProfileInt(_T("ObjValue"), _T("objvalue_y3"), 0, INI_FILE_NAME);
char text[20];
sprintf(text, "%d", dis_config.ObjValues[0]);
GetDlgItem(IDC_EDIT2)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.ObjValues[1]);
GetDlgItem(IDC_EDIT5)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.ObjValues[2]);
GetDlgItem(IDC_EDIT8)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.ObjValues[3]);
GetDlgItem(IDC_EDIT11)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.ObjValues[4]);
GetDlgItem(IDC_EDIT14)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.ObjValues[5]);
GetDlgItem(IDC_EDIT17)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.LimitOffset[0]);
GetDlgItem(IDC_EDIT3)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.LimitOffset[1]);
GetDlgItem(IDC_EDIT6)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.LimitOffset[2]);
GetDlgItem(IDC_EDIT9)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.LimitOffset[3]);
GetDlgItem(IDC_EDIT12)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.LimitOffset[4]);
GetDlgItem(IDC_EDIT15)->SetWindowTextA(text);
sprintf(text, "%d", dis_config.LimitOffset[5]);
GetDlgItem(IDC_EDIT18)->SetWindowTextA(text);
return dis_config;
}
void m_Dis::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, d_edit_log);
DDX_Control(pDX, IDC_STATIC_1, d_result);
DDX_Control(pDX, IDC_STATIC_4, d_QArate);
DDX_Control(pDX, IDC_STATIC_3, d_sum);
DDX_Control(pDX, IDC_STATIC_2, d_qa_sum);
DDX_Control(pDX, IDC_EDIT2, d_x1_value);
}
BOOL m_Dis::OnInitDialog()
{
CDialog::OnInitDialog();
d_distortonoaram=getdistorionparam();
UpdateData(TRUE);
d_qa_sum.SetWindowTextA(_T(""));
d_QArate.SetWindowTextA(_T(""));
d_result.SetWindowTextA(_T(""));
d_sum.SetWindowTextA(_T(""));
UpdateData(FALSE);
return TRUE;
}
void m_Dis::MatToCImage(Mat& mat, CImage& cimage)
{
if (0 == mat.total())
{
return;
}
int nChannels = mat.channels();
if ((1 != nChannels) && (3 != nChannels))
{
return;
}
int nWidth = mat.cols;
int nHeight = mat.rows;
//重建cimage
cimage.Destroy();
cimage.Create(nWidth, nHeight, 8 * nChannels);
//拷贝数据
uchar* pucRow;//指向数据区的行指针
uchar* pucImage = (uchar*)cimage.GetBits();//指向数据区的指针
int nStep = cimage.GetPitch();//每行的字节数,注意这个返回值有正有负
if (1 == nChannels)//对于单通道的图像需要初始化调色板
{
RGBQUAD* rgbquadColorTable;
int nMaxColors = 256;
rgbquadColorTable = new RGBQUAD[nMaxColors];
cimage.GetColorTable(0, nMaxColors, rgbquadColorTable);
for (int nColor = 0; nColor < nMaxColors; nColor++)
{
rgbquadColorTable[nColor].rgbBlue = (uchar)nColor;
rgbquadColorTable[nColor].rgbGreen = (uchar)nColor;
rgbquadColorTable[nColor].rgbRed = (uchar)nColor;
}
cimage.SetColorTable(0, nMaxColors, rgbquadColorTable);
delete[]rgbquadColorTable;
}
for (int nRow = 0; nRow < nHeight; nRow++)
{
pucRow = (mat.ptr<uchar>(nRow));
for (int nCol = 0; nCol < nWidth; nCol++)
{
if (1 == nChannels)
{
*(pucImage + nRow * nStep + nCol) = pucRow[nCol];
}
else if (3 == nChannels)
{
for (int nCha = 0; nCha < 3; nCha++)
{
*(pucImage + nRow * nStep + nCol * 3 + nCha) = pucRow[nCol * 3 + nCha];
}
}
}
}
}
void m_Dis::curve(Mat src, int num, DISTORTIONPARAMS distor)
{
d_edit_log.Clear();
m_iQA = 0;
if (src.empty())
return;
Mat dst;
Mat temp_src = src.clone();
if (temp_src.channels() == 3)
cvtColor(src, src, cv::COLOR_BGR2GRAY);
cv::threshold(src, dst, 125, 255, cv::THRESH_OTSU);
std::vector<std::vector<cv::Point>> contours_temp;
std::vector<cv::Vec4i> hierarchy;
findContours(dst, contours_temp, hierarchy, cv::RETR_LIST);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Point> centers;
CImage img;
MatToCImage(src, img);
int xt = src.cols;
int yt = src.rows;
CRect rectf;
int cx = img.GetWidth();
int cy = img.GetHeight();
CWnd *pWnd = GetDlgItem(IDC_STATIC_PIC);
if (pWnd == NULL)
return;
pWnd->GetClientRect(&rectf);
CDC *pDC = pWnd->GetDC();
SetStretchBltMode(pDC->m_hDC, STRETCH_HALFTONE);
int max = (cx >= cy) ? cx : cy;
float scale = (float)((float)max /460.0f);
int nw = (int)(cx / scale);
int nh = (int)(cy / scale);
CPoint pos = rectf.TopLeft();
rectf = CRect(pos, CSize(nw, nh));
img.Draw(pDC->m_hDC, rectf);
ReleaseDC(pDC);
for (int j = 0, count = contours_temp.size(); j < count; j++)
{
cv::Rect rect = cv::boundingRect(contours_temp[j]);
double area = cv::contourArea(contours_temp[j]);
if (area < 40000) continue;
double v = static_cast<double>(cv::pow((double)(rect.width + rect.height) / 4, 2) * 3.1415926535898 / area);
if (v > 0.9 && v < 1.1)
{
cv::Point center(rect.x + rect.width / 2, rect.y + rect.height / 2);
bool enable = true;
if (!centers.empty())
for (int i = 0; i < centers.size(); i++)
if (cv::pow((double)(centers[i].x - center.x), 2) + cv::pow((double)(centers[i].y - center.y), 2) < 200)
{
enable = false;
break;
}
if (enable)
{
contours.push_back(contours_temp[j]);
centers.push_back(center);
}
}
}
CString strX1, strX2, strX3, strY1, strY2, strY3, strInfo, strSum, strQA, strQArate;
CString strX1Dev, strX2Dev, strX3Dev, strY1Dev, strY2Dev, strY3Dev;
int m_itemp = cv::min(3, static_cast<int>(contours.size()));
if (m_itemp < 3)
{
m_iQA++;
}
for (int j = 0, count = m_itemp; j < count; j++)
{
cv::Rect rect = cv::boundingRect(contours[j]);
if (j == 0)
{
strX1.Format("%d", rect.width);
strY1.Format("%d", rect.height);
strX1Dev.Format("%d", rect.width - distor.ObjValues[0]);
strY1Dev.Format("%d", rect.height - distor.ObjValues[1]);
if (rect.width > (distor.ObjValues[0] + distor.LimitOffset[0]) || rect.width < (distor.ObjValues[0] - distor.LimitOffset[0]))
{
m_iQA++;
}
if (rect.height > (distor.ObjValues[1] + distor.LimitOffset[1]) || rect.height < (distor.ObjValues[1] - distor.LimitOffset[1]))
{
m_iQA++;
}
}
else if (j == 1)
{
strX2.Format("%d", rect.width);
strY2.Format("%d", rect.height);
strX2Dev.Format("%d", rect.width - distor.ObjValues[2]);
strY2Dev.Format("%d", rect.height - distor.ObjValues[3]);
if (rect.width > (distor.ObjValues[2] + distor.LimitOffset[2]) || rect.width < (distor.ObjValues[2] - distor.LimitOffset[2]))
{
m_iQA++;
}
if (rect.height > (distor.ObjValues[3] + distor.LimitOffset[3]) || rect.height < (distor.ObjValues[3] - distor.LimitOffset[3]))
{
m_iQA++;
}
}
else
{
strX3.Format("%d", rect.width);
strY3.Format("%d", rect.height);
strX3Dev.Format("%d", rect.width - distor.ObjValues[4]);
strY3Dev.Format("%d", rect.height - distor.ObjValues[5]);
if (rect.width > (distor.ObjValues[4] + distor.LimitOffset[4]) || rect.width < (distor.ObjValues[4] - distor.LimitOffset[4]))
{
m_iQA++;
}
if (rect.height > (distor.ObjValues[5] + distor.LimitOffset[5]) || rect.height < (distor.ObjValues[5] - distor.LimitOffset[5]))
{
m_iQA++;
}
}
}
if (m_iQA == 0)
{
//GetDlgItem(IDC_RESULT)->SetWindowTextA("Succeed");
m_QA_num++;
}
//else
//{
// //GetDlgItem(IDC_RESULT)->SetWindowTextA("Failed");
// CString csImage;
// csImage.Format("d:\\error\\%d.jpg", (num));
// IplImage qqImg;
// qqImg = IplImage(temp_src);
// cvSaveImage(csImage, &qqImg);
// csImage.ReleaseBuffer();
//}
strSum.Format("%d", num);
strQA.Format("%d", m_QA_num);
strQArate.Format("%0.2f", (float)m_QA_num * 100 / num);
d_sum.SetWindowTextA(strSum);
d_qa_sum.SetWindowTextA(strQA);
d_QArate.SetWindowTextA(strQArate);
d_result.SetWindowTextA(m_iQA == 0 ? "PASS" : "FAIL");
GetDlgItem(IDC_EDIT4)->SetWindowTextA(strX1Dev);
GetDlgItem(IDC_EDIT7)->SetWindowTextA(strY1Dev);
GetDlgItem(IDC_EDIT10)->SetWindowTextA(strX2Dev);
GetDlgItem(IDC_EDIT13)->SetWindowTextA(strY2Dev);
GetDlgItem(IDC_EDIT16)->SetWindowTextA(strX3Dev);
GetDlgItem(IDC_EDIT19)->SetWindowTextA(strY3Dev);
strInfo.Format("第%d张 ", num);
if (m_iQA == 0)
{
strInfo += "1-X:" + strX1+"\r\n" + " 1-Y:" + strY1+"\r\n" + " 2-X:" + strX2 + "\r\n" + " 2-Y:" + strY2 + "\r\n" + " 3-X:" + strX3 + "\r\n" + " 3-Y:" + strY3 + " Succeed";
}
else
{
strInfo += "1-X:" + strX1 + "\r\n" + " 1-Y:" + strY1 + "\r\n" + " 2-X:" + strX2 + "\r\n" + " 2-Y:" + strY2 + "\r\n" + " 3-X:" + strX3 + "\r\n" + " 3-Y:" + strY3 + " Failed";
}
string strTest;
strTest = CT2A(strInfo.GetString());
FileTools::write_log("D:\\Distor.txt", strTest);
CString ss;
if (m_iQA == 0)
{
ss.Format("%d、\r\n 1-X:\t%s\r\n 1-Y:\t%s\r\n 2-X:\t%s\r\n 2-Y:\t%s\r\n 3-X:\t%s\r\n 3-Y:\t%s\r\n Succeed", num, strX1, strY1, strX2, strY2, strX3, strY3);
}
else
{
ss.Format("%d、\r\n 1-X:\t%s\r\n 1-Y:\t%s\r\n 2-X:\t%s\r\n 2-Y:\t%s\r\n 3-X:\t%s\r\n 3-Y:\t%s\r\n Failed", num, strX1, strY1, strX2, strY2, strX3, strY3);
}
strTip = "";
strTip += ss;
strTip += "\r\n";
d_edit_log.SetWindowText(strTip);
d_edit_log.LineScroll(d_edit_log.GetLineCount());
int size = sizeof(strTip);
if (size > 1024)
strTip.Empty();
strX1.ReleaseBuffer();
strX2.ReleaseBuffer();
strX3.ReleaseBuffer();
strY1.ReleaseBuffer();
strY2.ReleaseBuffer();
strY3.ReleaseBuffer();
strInfo.ReleaseBuffer();
ss.ReleaseBuffer();
}
void m_Dis::findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy,int retr, int method , cv::Point offset )
{
CvMat c_image = src;
cv::MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
if (!_ccontours)
{
contours.clear();
return;
}
cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
size_t total = all_contours.size();
contours.resize(total);
cv::SeqIterator<CvSeq*> it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
int count = c->total;
int* data = new int[static_cast<size_t>(count * 2)];
cvCvtSeqToArray(c, data);
for (int j = 0; j < count; j++)
{
contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
}
delete[] data;
}
hierarchy.resize(total);
it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
}
storage.release();
}
BEGIN_MESSAGE_MAP(m_Dis, CDialog)
ON_BN_CLICKED(IDC_BUTTON1, &m_Dis::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON4, &m_Dis::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON6, &m_Dis::OnBnClickedButton6)
ON_BN_CLICKED(IDC_BUTTON7, &m_Dis::OnBnClickedButton7)
END_MESSAGE_MAP()
// m_Dis 消息处理程序
void m_Dis::OnBnClickedButton1()
{
//TODO: 在此添加控件通知处理程序代码
if (!d_drv->IsConnected())
{
MessageBox("扫描仪未连接!");
return;
}
CString hvs;
GetDlgItemText(IDC_EDIT20, hvs);
CString vvs;
GetDlgItemText(IDC_EDIT23, vvs);
float hv = _ttof(hvs.Trim().GetBuffer());
float vv = _ttof(vvs.Trim().GetBuffer());
d_drv->Set_Scanner_Correct_Ratio(hv, vv);
}
void m_Dis::OnBnClickedButton4()
{
//TODO: 在此添加控件通知处理程序代码
if (!d_drv->IsConnected())
{
MessageBox("扫描仪未连接!");
return;
}
std::string fwv;
fwv=d_drv->GetFWVersion();
std::string text = "当前版本为:" + fwv + "!\n版本过低,不支持读取!";
if (atoi(fwv.substr(fwv.length() - 3, fwv.length() - 1).c_str()) < 14)
{
MessageBox(text.c_str());
return;
}
float hv, vv;
d_drv->Get_Scanner_Correct_Ratio(hv, vv);
CString hvs;
hvs.Format(_T("% .4f"), hv);
SetDlgItemText(IDC_EDIT22, hvs);
CString vvs;
vvs.Format(_T("% .4f"), vv);
SetDlgItemText(IDC_EDIT21, vvs);
}
void m_Dis::OnBnClickedButton6()
{
// TODO: 在此添加控件通知处理程序代码
getdistorionparam();
}
void m_Dis::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码
updatadistorionparam();
}