// CIS.cpp: 实现文件 // #include "stdafx.h" #include "HuaGoCorrect.h" #include "CIS.h" #include "afxdialogex.h" #include // CIS 对话框 IMPLEMENT_DYNAMIC(CIS, CDialog) CIS::CIS(CWnd* pParent /*=nullptr*/ ) : CDialog(IDD_CIS_DIALOG1, pParent), b_run(false), C_drv(NULL), b_canget(false) , c_channel(0) , spin_up(50) , spin_low(30) , spin_area_up(400) , spin_area_low(400) , isduplex(true) { b_run = true; c_thread = std::thread(&CIS::Cis_start,this); /* * 构造函数 把Gscn——drv对象传进来 * gscan——drv.aquireimage * mat转换成picturebox支持的图像格式 */ } CIS::~CIS() { if (c_thread.joinable()) { b_run = false; c_thread.join(); } } void CIS::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, m_list); DDX_Control(pDX, IDC_COMBO1, Cis_box); DDX_CBIndex(pDX, IDC_COMBO1, c_channel); DDX_Text(pDX, IDC_EDIT2, spin_up); DDX_Text(pDX, IDC_EDIT3, spin_low); DDX_Text(pDX, IDC_EDIT4, spin_area_up); DDX_Text(pDX, IDC_EDIT5, spin_area_low); DDX_Control(pDX, IDC_EDIT2, edit_up); DDX_Control(pDX, IDC_EDIT3, edit_low); DDX_Control(pDX, IDC_EDIT4, edit_area_up); DDX_Control(pDX, IDC_EDIT5, edit_area_low); } int num = 0; int row = 0; void CIS::Cis_start() { while (b_run) { if (b_canget) { if (C_drv) { if (!C_drv->Get_IsImageQueueEmpty()) { cv::Mat mat; C_drv->aquire_image(mat); detect_start(mat); } } } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } void CIS::get_config() { char text[20]; spin_up = ::GetPrivateProfileInt(_T("CIS"), _T("total_up"), 0, INI_FILE_NAME); spin_low = ::GetPrivateProfileInt(_T("CIS"), _T("total_low"), 0, INI_FILE_NAME); spin_area_up = ::GetPrivateProfileInt(_T("CIS"), _T("total_area_up"), 0, INI_FILE_NAME); spin_area_low = ::GetPrivateProfileInt(_T("CIS"), _T("total_area_low"), 0, INI_FILE_NAME); c_channel = ::GetPrivateProfileInt(_T("CIS"), _T("channle"), 0, INI_FILE_NAME); sprintf(text, "%d", spin_up); edit_up.SetWindowTextA(text); sprintf(text, "%d", spin_low); edit_low.SetWindowTextA(text); sprintf(text, "%d", spin_area_up); edit_area_up.SetWindowTextA(text); sprintf(text, "%d", spin_area_low); edit_area_low.SetWindowTextA(text); Cis_box.SetCurSel(c_channel); } void CIS::set_config() { CString text[5]; edit_up.GetWindowTextA(text[0]); edit_low.GetWindowTextA(text[1]); edit_area_up.GetWindowTextA(text[2]); edit_area_low.GetWindowTextA(text[3]); text[4].Format("%d", c_channel); ::WritePrivateProfileString(_T("CIS"), _T("total_up"), _T(text[0]), INI_FILE_NAME); ::WritePrivateProfileString(_T("CIS"), _T("total_low"), _T(text[1]), INI_FILE_NAME); ::WritePrivateProfileString(_T("CIS"), _T("total_area_up"), _T(text[2]), INI_FILE_NAME); ::WritePrivateProfileString(_T("CIS"), _T("total_area_low"), _T(text[3]), INI_FILE_NAME); ::WritePrivateProfileString(_T("CIS"), _T("channle"), _T(text[4]), INI_FILE_NAME); } BOOL CIS::OnInitDialog() { CDialog::OnInitDialog(); UpdateData(TRUE); CRect rect; m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); m_list.GetClientRect(&rect); m_list.InsertColumn(0, _T("类型"), LVCFMT_CENTER, rect.Width() / 3, 0); m_list.InsertColumn(1, _T("值%"), LVCFMT_CENTER, rect.Width() / 3, 1); m_list.InsertColumn(2, _T("合格"), LVCFMT_CENTER, rect.Width() / 3, 2); Cis_box.InsertString(0, _T("R")); Cis_box.InsertString(1, _T("G")); Cis_box.InsertString(2, _T("B")); get_config(); UpdateData(false); // TODO: 在此添加额外的初始化 return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CIS::SetGscan_drv(GScn_Drv* c_drv) { if (C_drv != c_drv) { C_drv = c_drv; } } //std::vector image_bgr; void CIS::detect_start(cv::Mat& image) { //image_bgr.clear(); if (!isduplex) { num = 0; m_list.DeleteAllItems(); } if(row==0) m_list.DeleteAllItems(); c_channel = Cis_box.GetCurSel(); if (image.empty()) return; cv::Mat src; if (image.channels() == 3) { cv::Mat image_bgr[3]; cv::split(image, image_bgr); src = image_bgr[c_channel].clone(); } else src = image.clone(); Cis_box.EnableWindow(image.channels() == 3); double average = cv::mean(src)[0]; Result r_low = lessenColor(src, cv::Range(0, average - spin_up), spin_low); Result r_up = lessenColor(src, cv::Range(average +spin_up, 256), spin_low); if (src.cols % 4 != 0) cv::copyMakeBorder(src, src, 0, 0, 0, 4 - (src.cols % 4), cv::BORDER_CONSTANT); cv::cvtColor(src, src, cv::COLOR_GRAY2BGR); cv::drawContours(src, r_low.contours, -1, cv::Scalar(255, 0, 0)); cv::drawContours(src, r_up.contours, -1, cv::Scalar(0, 0, 255)); CImage img; MatToCImage(image, img); int xt = image.cols; int yt = image.rows; CRect rectf; int cx = img.GetWidth(); int cy = img.GetHeight(); CWnd *pWnd = GetDlgItem(IDC_STATIC_PICTURE_CIS); pWnd->GetClientRect(&rectf); CDC *pDC = pWnd->GetDC(); SetStretchBltMode(pDC->m_hDC, STRETCH_HALFTONE); int max = (cx >= cy) ? cx : cy; float scale; scale = (float)((float)max / 260.0f); int nw = (int)(cx / scale); int nh = (int)(cy / scale); CPoint pos= rectf.TopLeft(); if (num == 0) { rectf = CRect(pos, CSize(nw, nh)); rect_front = rectf; img_front = img; } else { pos = CPoint(0, nh); rectf = CRect(pos,CSize(nw,nh)); rect_reverse = rectf; img_reverse = img; } img.Draw(pDC->m_hDC, rectf); ReleaseDC(pDC); img.Destroy(); //ui->tableWidget->setRowCount(r_low.area.size() + r_up.area.size() + 3); double total = src.total(); double total_up = 0; double total_low = 0; if (num == 0) { if(isduplex) row=m_list.InsertItem(0, (LPCTSTR)"正面"); m_list.SetItemText(row, 1, (LPCTSTR)""); m_list.SetItemText(row, 2, (LPCTSTR)""); } else { row=m_list.InsertItem(0, (LPCTSTR)"反面"); m_list.SetItemText(row, 1, (LPCTSTR)""); m_list.SetItemText(row, 2, (LPCTSTR)""); } row++; for (size_t i = 0; i < r_low.area.size(); i++) { CString text; text.Format(_T("暗斑%d"), i); row=m_list.InsertItem(row, (LPCTSTR)text); text.Format(_T("%lf"), r_low.area[i] * 100 / total); m_list.SetItemText(row, 1, (LPCTSTR)text); total_low += r_low.area[i] * 100 / total; if ((r_low.area[i] * 100 / total) <= spin_low) m_list.SetItemText(row, 2, (LPCTSTR)"通过"); else m_list.SetItemText(row, 2, (LPCTSTR)"不通过"); row++; } for (size_t i = 0; i < r_up.area.size(); i++) { CString text; text.Format(_T("亮斑%d"),i+ r_low.area.size()); row =m_list.InsertItem(i+ r_low.area.size(), text); text.Format(_T("%lf"), r_low.area[i] * 100 / total); m_list.SetItemText(row, 1, text); total_up += r_up.area[i] * 100 / total; if ((r_up.area[i] * 100 / total) <= spin_up) m_list.SetItemText(row, 2, (LPCTSTR)"通过"); else m_list.SetItemText(row, 2, (LPCTSTR)"不通过"); row++; } CString text_0[3] = { "亮斑面积" ,"暗斑面积" ,"剩余面积" }; for (int i = 0; i < 3;i++) { CString text; m_list.InsertItem(row, text_0[i]); if (i == 0) text.Format(_T("%lf"), total_up); else text.Format(_T("%lf"), total_low); m_list.SetItemText(row, 1, text); if (i == 0) { if (total_up <= spin_area_up) m_list.SetItemText(row, 2, (LPCTSTR)"通过"); else m_list.SetItemText(row, 2, (LPCTSTR)"不通过"); } else if (i == 1) { if (total_low <= spin_area_low) m_list.SetItemText(row, 2, (LPCTSTR)"通过"); else m_list.SetItemText(row, 2, (LPCTSTR)"不通过"); } else { text.Format(_T("%lf"), 100-total_low- total_up); m_list.SetItemText(row, 1, text); } row++; } num++; if (num > 1) { num = 0; row = 0; } } void CIS::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(); } void CIS::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]; } } } } } Result CIS::lessenColor(const cv::Mat &image, cv::Range range, int areaThre) { cv::Mat thre; cv::inRange(image, range.start, range.end, thre); std::vector> contours; std::vector hierarchy; findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); Result result; for (int i = 0; i < contours.size(); i++) { double area = cv::contourArea(contours[i]); if (area >= areaThre) { result.contours.push_back(contours[i]); result.area.push_back(static_cast(area)); } } return result; } BEGIN_MESSAGE_MAP(CIS, CDialog) ON_CBN_SELCHANGE(IDC_COMBO1, &CIS::OnCbnSelchangeCombo1) ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN3, &CIS::OnDeltaposSpin3) ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN4, &CIS::OnDeltaposSpin4) ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN5, &CIS::OnDeltaposSpin5) ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN6, &CIS::OnDeltaposSpin6) ON_WM_PAINT() END_MESSAGE_MAP() // CIS 消息处理程序 void CIS::OnCbnSelchangeCombo1() { // TODO: 在此添加控件通知处理程序代码 c_channel = Cis_box.GetCurSel(); } void CIS::OnDeltaposSpin3(NMHDR *pNMHDR, LRESULT *pResult) { LPNMUPDOWN pNMUpDown = reinterpret_cast(pNMHDR); // TODO: 在此添加控件通知处理程序代码 *pResult = 0; if (pNMUpDown->iDelta == -1) { spin_up += 1; } else if(pNMUpDown->iDelta==1) { spin_up -= 1; } char text[10]; itoa(spin_up, text, 10); edit_up.SetWindowTextA(text); } void CIS::OnDeltaposSpin4(NMHDR *pNMHDR, LRESULT *pResult) { LPNMUPDOWN pNMUpDown = reinterpret_cast(pNMHDR); // TODO: 在此添加控件通知处理程序代码 *pResult = 0; if (pNMUpDown->iDelta == -1) { spin_low += 1; } else if (pNMUpDown->iDelta == 1) { spin_low -= 1; } char text[10]; itoa(spin_low, text, 10); edit_low.SetWindowTextA(text); } void CIS::OnDeltaposSpin5(NMHDR *pNMHDR, LRESULT *pResult) { LPNMUPDOWN pNMUpDown = reinterpret_cast(pNMHDR); // TODO: 在此添加控件通知处理程序代码 *pResult = 0; if (pNMUpDown->iDelta == -1) { spin_area_up += 1; } else if (pNMUpDown->iDelta == 1) { spin_area_up -= 1; } char text[10]; itoa(spin_area_up, text, 10); edit_area_up.SetWindowTextA(text); } void CIS::OnDeltaposSpin6(NMHDR *pNMHDR, LRESULT *pResult) { LPNMUPDOWN pNMUpDown = reinterpret_cast(pNMHDR); // TODO: 在此添加控件通知处理程序代码 *pResult = 0; if (pNMUpDown->iDelta == -1) { spin_area_low += 1; } else if (pNMUpDown->iDelta == 1) { spin_area_low -= 1; } char text[10]; itoa(spin_area_low, text, 10); edit_area_low.SetWindowTextA(text); } void CIS::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: 在此处添加消息处理程序代码 // 不为绘图消息调用 CDialog::OnPaint() //if (img_front == NULL) //重绘扫描到的图片,实现切换界面不刷新,但draw时程序崩溃,原因还未知 // return; //CWnd *pWnd = GetDlgItem(IDC_STATIC_PICTURE_CIS); //CImage *image = &img_front; //pWnd->GetClientRect(&rect_front); //CDC *pDC = pWnd->GetDC(); //SetStretchBltMode(pDC->m_hDC, STRETCH_HALFTONE); //CPoint pos = rect_front.TopLeft(); //image->Draw(pDC->m_hDC, rect_front); //ReleaseDC(pDC); //image->Destroy(); //delete image; }