这是本人第一次正儿八经非调侃的态度写C相关的东西;
VS的C++每次环境不好配置就让人望而却步;
而python的优势在于环境几乎只需要pip install xxx;
C# 多数情况下nuget 点点点在添加引用就能愉快的玩耍;
而 py C# 背后 竟然是 xxx; 有一 被分层包养的感觉;
而C/CPP 头文件 程序 链接文件(动态|静态) 动态链接库 这都啥??
掌握pythonnet ctypes 咯咯咯嘎嘎嘎 %$#@#$%&^*(&(python?nodejs?Electron??
呃呃呃:python 版的 opencv halcon 图像变量互相转换前面已经讲过了.
作为一个python用户还是要玩C的; 不吹牛开始第一步哈喽沃德吧.
平台:
平台:
操作系统: Win10 22H2 64 位操作系统, 基于 x64 的处理器
IDE: Microsoft Visual Studio 2022 (64 位)
CV: opencv4.9
HA: HALCON-23.05
环境配置:
1.默认Win10_X64已经安装好了VS2022 且可以正常编译C++工程;
2.已经安装好mvtec-chalcon23.05 ;
默认安装路径:
"C:\Program Files\MVTec\HALCON-23.05-Progress";
"C:\Program Files\MVTec\HALCON-23.05-Progress\bin\x64-win64";
3.已经下载好opencv:"opencv-4.9.0-windows.exe":
运行后自动解压>>:
"D:\下载\opencv_\opencv4.9";
"D:\下载\opencv_\opencv4.9\build";
"opencv4.9\build\x64\vc16\bin"
4.首先新建一个C++工程"控制台应用":
工程文件夹下会产生:
xxx.sln
xxx.vcxproj
xxx.vcxproj.filters
xxx.vcxproj.user
xxx.cpp
x64
主要关注:xxx.vcxproj:
所有工程配置信息以类似xml文本保存到该文件;
相对路径也是以该文件位置为基准;
5.在工程下xxx.vcxproj文件同级目录新建两个文件夹:
新建HALCON-23.05-Progress:
将"C:\Program Files\MVTec\HALCON-23.05-Progress"
,内的 "include" "lib"文件夹复制进来
新建opencv4.9:
将"D:\下载\opencv_\opencv4.9\build";
,内的"include" "x64"文件夹复制进来
6.
先在"配置管理器":
活动解决方案平台 活动解决方案配置
设置好 X64 Release Debug
接下来:
项目>>属性(配置属性):
VC++目录:
"包含目录":
{
opencv4.9\include
opencv4.9\include\opencv2
HALCON-23.05-Progress\include
HALCON-23.05-Progress\include\halconcpp
}
"库目录":
{
opencv4.9\x64\vc16\lib
HALCON-23.05-Progress\lib\x64-win64
}
链接器:
常规:
"附加库目录":
{
HALCON-23.05-Progress\lib\x64-win64
}
输入:
"附加依赖项":
{
halconcpp.lib
opencv_world490.lib
}
7.总结:
项目>>属性(配置属性):
VC++目录:
"包含目录":(1)
"库目录":(2)
链接器:
常规:
"附加库目录":(3)
输入:
"附加依赖项":(4)
程序前面加:
和 附加依赖项 都行
没搞明白有啥不一样;
两个都搞上也行;
#pragma comment(lib, "opencv_world490.lib")
#pragma comment(lib, "opencv_world490d.lib")
#pragma comment(lib, "halconcpp.lib")
实际上一共四步:
"包含目录":(1)
opencv4.9\include
opencv4.9\include\opencv2
HALCON-23.05-Progress\include\halconcpp
HALCON-23.05-Progress\include
"库目录":(2)
opencv4.9\x64\vc16\lib
HALCON-23.05-Progress\lib\x64-win64
"附加库目录":(3)
HALCON-23.05-Progress\lib\x64-win64
"附加依赖项":(4)
halconcpp.lib
opencv_world490d.lib
接下来:
配置完成后:用记事本打开xxx.vcxproj文件:
会发现 这些标签: (反正我看不懂 大概就这意思)
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>
opencv4.9\include;
opencv4.9\include\opencv2;
HALCON-23.05-Progress\include\halconcpp;
HALCON-23.05-Progress\include;
$(IncludePath)
</IncludePath>
<LibraryPath>
opencv4.9\x64\vc16\lib;
HALCON-23.05-Progress\lib\x64-win64;
$(LibraryPath)
</LibraryPath>
</PropertyGroup>
8.测试程序是否能正常编译生成:
"xxx\x64\Release xxx.exe"
正常生成后还需要运行:
从这里:
"C:\Program Files\MVTec\HALCON-23.05-Progress\bin\x64-win64"
复制
halcon.dll
halconc.dll
halconcpp.dll
hcanvas.dll
halcondl.dll
halcondlxl.dll
halconxl.dll
halconcxl.dll
halconcppxl.dll
到xxx.exe同级目录:
从这里:
"opencv4.9\build\x64\vc16\bin"
复制:
opencv_world490.dll
opencv_world490d.dll
opencv_videoio_msmf490_64.dll
opencv_videoio_msmf490_64d.dll
opencv_videoio_ffmpeg490_64.dll
到xxx.exe同级目录:
就可以运行了:
不用添加opencv环境变量:
这个工程可以打包 到只有VS 没有安装opencv halcon的机器;
缺点是opencv dll文件很大
提示 :
不用添加opencv环境变量:
这个工程可以打包 到只有VS 没有安装opencv halcon的机器也是没有问题的;
接下来: 上程序: 转换很丝滑;
#include <iostream>
#pragma comment(lib, "opencv_world490.lib")
//#pragma comment(lib, "opencv_world490d.lib")
#pragma comment(lib, "halconcpp.lib")
#include "opencv.hpp"
#include "highgui.hpp"
#include "HalconCpp.h"
#include "HDevThread.h"
using namespace std;
using namespace cv;
using namespace HalconCpp;
cv::Mat HImageToMat(HalconCpp::HObject& H_img)
{
cv::Mat cv_img, cv_imgr, cv_imgg, cv_imgb;
HalconCpp::HTuple channels, w, h;
HalconCpp::ConvertImageType(H_img, &H_img, "byte");
HalconCpp::CountChannels(H_img, &channels);
if (channels.I() == 1)
{
HalconCpp::HTuple pointer;
GetImagePointer1(H_img, &pointer, nullptr, &w, &h);
int width = w.I(), height = h.I();
int size = width * height;
cv_img = cv::Mat::zeros(height, width, CV_8UC1);
memcpy(cv_img.data, (void*)(pointer.L()), size);
}
else if (channels.I() == 3)
{
HalconCpp::HTuple pointerR, pointerG, pointerB;
HalconCpp::GetImagePointer3(H_img, &pointerR, &pointerG, &pointerB, nullptr, &w, &h);
int width = w.I(), height = h.I();
int size = width * height;
cv_imgr = cv::Mat::zeros(height, width, CV_8UC1);
cv_imgg = cv::Mat::zeros(height, width, CV_8UC1);
cv_imgb = cv::Mat::zeros(height, width, CV_8UC1);
cv_img = cv::Mat::zeros(height, width, CV_8UC3);
memcpy(cv_imgr.data, (void*)(pointerR.L()), size);
memcpy(cv_imgg.data, (void*)(pointerG.L()), size);
memcpy(cv_imgb.data, (void*)(pointerB.L()), size);
vector<Mat> imgv;
imgv.push_back(cv_imgb);
imgv.push_back(cv_imgg);
imgv.push_back(cv_imgr);
cv::merge(imgv, cv_img);
uchar* R = (uchar*)(pointerR.L());
uchar* G = (uchar*)(pointerG.L());
uchar* B = (uchar*)(pointerB.L());
}
return cv_img;
}
HalconCpp::HImage MatToHImage(const cv::Mat& mat)
{
HalconCpp::HImage hImg;
int hgt = mat.rows;
int wid = mat.cols;
int channels = mat.channels();
switch (channels)
{
case 1:
{
// Assuming the image is single channel (grayscale)
HalconCpp::GenImage1(&hImg, "byte", wid, hgt, (Hlong)mat.data);
break;
}
case 3:
{
// Assuming the image is 3 channel (BGR in OpenCV)
cv::Mat rgbMat;
cv::cvtColor(mat, rgbMat, cv::COLOR_BGR2RGB);
hImg.GenImageInterleaved(rgbMat.data, "rgb", wid, hgt, 0, "byte", wid, hgt, 0, 0, -1, 0);
break;
}
// Add more cases as needed for different number of channels
}
return hImg;
}
void action()
{
SetSystem("use_window_thread", "true");
SetHcppInterfaceStringEncodingIsUtf8(false);
SetSystem("width", 512);
SetSystem("height", 512);
HObject ho_Image;
HTuple hv_WindowHandle;
ReadImage(&ho_Image, "printer_chip/printer_chip_01");
SetWindowAttr("background_color", "black");
OpenWindow(0, 0, 512, 512, 0, "visible", "", &hv_WindowHandle);
DispObj(ho_Image, hv_WindowHandle);
ClearWindow(hv_WindowHandle);
}
void opcv()
{
Mat img = imread("C://Users//Administrator//Desktop//opencv_C++_halcon_转换//ha_ft_cv_conv//x64//Release//012.jpg");
namedWindow("窗口", WINDOW_AUTOSIZE | WINDOW_NORMAL);
cv::imshow("窗口", img);
//while (char(waitKey(1)) != 'q') {}
waitKey(2000);
}
void convtt()
{
Mat img = imread("C:/lena4.jpg");
Mat M1(600, 600, CV_8UC3, cv::Scalar(255, 0, 0));
//Mat M1(600, 600, CV_8UC4, cv::Scalar(255, 0, 0,255));// 4通道
namedWindow("kl", 1);cv::imshow("kl", M1);waitKey(2000);
//halcon 转CV mat
HalconCpp::HImage H_img("C:/LenaNO.jpg"); //
HalconCpp::HImage H_gray;
HalconCpp::Rgb1ToGray(H_img, &H_gray); //
cv::Mat cv_imgHgray = HImageToMat(H_gray);//1通道
namedWindow("kl", 1);cv::imshow("kl", cv_imgHgray);waitKey(2000);
cv::Mat cv_imgH = HImageToMat(H_img); // 3通道
namedWindow("kl", 1); cv::imshow("kl", cv_imgH); waitKey(2000);
//CV mat 转 halcon
/****************************************************************************************/
cv::Mat mat = cv::imread("C:/lena1.png");
HalconCpp::HImage hImg = MatToHImage(mat);//3通道
Mat img_gray = imread("C:/lena1.png", 0);
HalconCpp::HImage hImg_gray = MatToHImage(img_gray);//灰度1通道
HTuple hv_WindowHandle, hv_WindowHandle1;
SetSystem("use_window_thread", "true");
SetHcppInterfaceStringEncodingIsUtf8(false);
SetSystem("width", 512);
SetSystem("height", 512);
SetWindowAttr("background_color", "black");
OpenWindow(0, 0, 512, 512, 0, "visible", "", &hv_WindowHandle);
OpenWindow(0, 512, 512, 512, 0, "visible", "", &hv_WindowHandle1);
DispObj(hImg, hv_WindowHandle);
DispObj(hImg_gray, hv_WindowHandle1);
Sleep(3000);
}
int main(int argc, char* argv[], char** env)
{
cout << argc << argv[0];
action();//单独试试halcon行不行
opcv(); //单独试试cv行不行
convtt();//测试单通道三通道互相转换
return 0;
}
本来到这里已经结束了,突然想比较一下python版本和C++的速度;来开始:
先上python:
import os,cv2,time
import halcon as ha
import numpy as np
from ctypes import *
def cmd(s="pause"):
os.system(s)
def open_window(width, height,row=0,column=0,father_window=0):
if os.name == 'nt':
ha.set_system('use_window_thread', 'true')
return ha.open_window(
row=row,
column=column,
width=width,
height=height,
father_window=0,
mode='visible',
machine=''
)
def ha_ha_2_np(image):
before = time.time()
img=ha.himage_as_numpy_array(image)
img_bgr=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
after = time.time()
time_consuming=after-before
return time_consuming,img_bgr
def hanp__2_ha(img):
before = time.time()
img_bgr=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
image=ha.himage_from_numpy_array(img_bgr)
after = time.time()
time_consuming=after-before
return time_consuming,image
if __name__ == "__main__":
Image = ha.read_image('Lena1')
ty,img=ha_ha_2_np(Image)
#img_bgr=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
print(f"python:halcon转numpy耗时:{ty}")
ty,h_img=hanp__2_ha(img)
print(f"python:numpy转halcon耗时:{ty}")
Width, Height = ha.get_image_size(Image)
print(Width[0], Height[0])
WindowHandle =open_window(Width[0]/2, Height[0]/2)
gray = ha.rgb1_to_gray(Image)
thres = ha.threshold(gray, 100, 200)
ha.disp_obj(Image, WindowHandle);cmd()
ha.clear_window(WindowHandle)
ha.disp_obj(thres, WindowHandle);cmd()
运行结果:
python:halcon转numpy耗时:0.00398707389831543
python:numpy转halcon耗时:0.001956939697265625
512 512
请按任意键继续. . .
请出C:
//记得#include <iostream> #include <chrono>
void convtttime()
{
//halcon 转CV mat
HalconCpp::HImage H_img("C://Lena1.png"); // 拿图
auto start = std::chrono::high_resolution_clock::now();
cv::Mat cv_imgH = HImageToMat(H_img); // 3通道 转换
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = end - start;
printf("\n");
std::cout << "halcon 转CV mat: " << elapsed.count() << "s\n";
namedWindow("kl", 1); cv::imshow("kl", cv_imgH); waitKey(1);//显示
//CV mat 转 halcon
/**********************************************************************************/
cv::Mat mat = cv::imread("C://Lena1.png");
auto start1 = std::chrono::high_resolution_clock::now();
HalconCpp::HImage hImg = MatToHImage(mat);//3通道
auto end1 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed1 = end1 - start1;
printf("\n");
std::cout << "CV mat 转 halcon: " << elapsed1.count() << "s\n";
HTuple hv_WindowHandle, hv_WindowHandle1;
SetSystem("use_window_thread", "true");
SetHcppInterfaceStringEncodingIsUtf8(false);
SetSystem("width", 512);
SetSystem("height", 512);
SetWindowAttr("background_color", "black");
OpenWindow(0, 0, 512, 512, 0, "visible", "", &hv_WindowHandle);
DispObj(hImg, hv_WindowHandle); //显示
Sleep(30000);
}
int main(int argc, char* argv[], char** env)
{
cout << argc << argv[0];
convtttime();
return 0;
}
最后看运行结果:
1C:\Users\Administrator\Desktop\opencv_C++_halcon_转换\ha_ft_cv_conv\x64\Release\ha_ft_cv_conv.exe
halcon 转CV mat: 0.001906s
CV mat 转 halcon: 0.0005785s
对比不明显:把两个结果放在一起来看:
C++:
1C:\Users\Administrator\Desktop\opencv_C++_halcon_转换\ha_ft_cv_conv\x64\Release\ha_ft_cv_conv.exe
halcon 转CV mat: 0.001906s
CV mat 转 halcon: 0.0005785s
python:
python:halcon转numpy耗时:0.0049591064453125
python:numpy转halcon耗时:0.000993490219116211
512 512
同样一张图:
halcon 转 CV 前者比后者快了2.6倍;
CV 转 halcon 前者比后者快 几乎2倍
然而 不是说python出了名的慢,比C慢几十倍上百倍么;
你会发现py竟然比C#的halconnet >>互转<<opencvsharp快??
这就是争吵的原因;
当然脱离实际情况的争吵属于耍无赖;具体问题具体分析;
纯cli:
如果是QT那么你得把C:\Qt\Qt5.14.2\5.14.2\msvc2017_64\bin
150多个dll共计600M的依赖文件拿过来 图转成RGB888 这不得拖慢多少倍