// 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(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> contours_temp; std::vector hierarchy; findContours(dst, contours_temp, hierarchy, cv::RETR_LIST); std::vector> contours; std::vector 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(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(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>& contours, std::vector& 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 all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); size_t total = all_contours.size(); contours.resize(total); cv::SeqIterator it = all_contours.begin(); for (size_t i = 0; i < total; i++, ++it) { CvSeq* c = *it; reinterpret_cast(c)->color = static_cast(i); int count = c->total; int* data = new int[static_cast(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(c->h_next)->color : -1; int h_prev = c->h_prev ? reinterpret_cast(c->h_prev)->color : -1; int v_next = c->v_next ? reinterpret_cast(c->v_next)->color : -1; int v_prev = c->v_prev ? reinterpret_cast(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(); }