huago-corrcet_tools/HuaGoCorrect/CIS.cpp

541 lines
14 KiB
C++
Raw Permalink Normal View History

2020-08-31 08:08:50 +00:00
// 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);
/*
* Gscndrv对象传进来
* gscandrv.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;
}