huago-corrcet_tools/HuaGoCorrect/CIS.cpp

541 lines
14 KiB
C++
Raw Permalink 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.

// CIS.cpp: 实现文件
//
#include "stdafx.h"
#include "HuaGoCorrect.h"
#include "CIS.h"
#include "afxdialogex.h"
#include <thread>
// 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<cv::Mat> 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<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();
}
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<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];
}
}
}
}
}
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<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> 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<int>(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<LPNMUPDOWN>(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<LPNMUPDOWN>(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<LPNMUPDOWN>(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<LPNMUPDOWN>(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;
}