今天窩了一整天的宿舍,內心被程式與高溫弄得有點心煩,趁著傍晚天氣較涼到附近公園溜搭,走著走著,竟傳來久違的夏天氣息,那就是在樹上高歌的蟬聲,如此熱鬧般的蟬聲,對比人行道空冷的寂靜,顯得格外諷刺,看來這個夏天依舊不寧靜,願這疫情能早點結束,讓生活回到從前般的開心!!
2021年5月24日 星期一
2021年3月30日 星期二
Git 版本管控(一)-淺談版本管控
2021年3月20日 星期六
C# 使用C++ DLL檔(回傳值)
延續上篇(C# 使用C++ DLL檔)之後,一般使用DLL時,除了將參數提供給DLL演算法做使用,也需將演算法結果從DLL回傳回去,所以這次就來說明如何回傳結果給C#吧。
目前我了解到如果要從DLL回傳結果給C#,都會使用指標做回傳,而我先前測試經驗,C++撰寫上比較不會遇到問題,但在接收端C#有遇過接不到數值、接錯值、或是跑久還造成程式當掉,重點是DLL除錯還不怎麼容易,像是瞎子摸象的感覺,如果有人知道怎樣較快除DLL的Bug,再歡迎留言告訴我,感謝!!!經過一番的測試之後,我目前可正常回傳的資訊分別為字串與float陣列資訊。
Extern.cpp
#ifdef SYSALGORITHM_EXPORTS
#define SYSALGORITHM_API __declspec(dllexport)
#include "SysAlgorithm.h"
extern "C" SYSALGORITHM_API int add(int a, int b)
{
Calculator Calculator;
return Calculator.add(a, b);
}
extern "C" SYSALGORITHM_API int subtract(int a, int b)
{
Calculator Calculator;
return Calculator.subtract(a, b);
}
extern "C" SYSALGORITHM_API void getDLLValue(float * DLLvalue)
{
Calculator Calculator;
return Calculator.getDLLValue(DLLvalue);
}
extern "C" SYSALGORITHM_API void getDLLInfo(char * DLLInfo)
{
Calculator Calculator;
return Calculator.getDLLInfo(DLLInfo);
}
#endif
SysAlgorithm.h
#pragma once
#ifndef SYSALGORITHM_H
#define SYSALGORITHM_H
#include <fstream>
#include <string>
class Calculator
{
public:
Calculator();
~Calculator();
int add(int a, int b);
int subtract(int a, int b);
void getDLLValue(float * DLLvalue);
void getDLLInfo(char * DLLInfo);
};
#endif // !SYSALGORITHM_H
SysAlgorithm.cpp
#include "SysAlgorithm.h"
Calculator::Calculator()
{
}
Calculator::~Calculator()
{
}
int Calculator::add(int a, int b)
{
return(a + b);
}
int Calculator::subtract(int a, int b)
{
return(a - b);
}
void Calculator::getDLLValue(float * DLLvalue)
{
DLLvalue[0] = 0;
DLLvalue[1] = 1.2;
DLLvalue[2] = -1.2;
}
void Calculator::getDLLInfo(char * DLLInfo)
{
char Info[20] = " return DLLInfo";
strcpy_s(DLLInfo, strlen(Info) + 1, Info);
}
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace SysUI
{
public partial class Form1 : Form
{
[DllImport("SysAlgorithm.dll", EntryPoint = "add", CallingConvention = CallingConvention.Cdecl)]
private static extern int add(int a, int b);
[DllImport("SysAlgorithm.dll", EntryPoint = "subtract", CallingConvention = CallingConvention.Cdecl)]
private static extern int subtract(int a, int b);
[DllImport("SysAlgorithm.dll", EntryPoint = "getDLLValue", CallingConvention = CallingConvention.Cdecl)]
private static extern void getDLLValue([MarshalAs(UnmanagedType.LPArray)]float[] value);
[DllImport("SysAlgorithm.dll", EntryPoint = "getDLLInfo", CallingConvention = CallingConvention.Cdecl)]
private static extern void getDLLInfo(StringBuilder DLLInfo);
private StringBuilder DLLInfo = new StringBuilder(20);
private float[] DLLvalue = new float[3];
public Form1()
{
InitializeComponent();
label1.Text = add(3, 5).ToString();
label2.Text = subtract(3, 5).ToString();
getDLLValue(DLLvalue);
getDLLInfo(DLLInfo);
label6.Text = DLLvalue[0].ToString() + "," + DLLvalue[1].ToString("F2") + "," + DLLvalue[2].ToString("F2");
label8.Text = DLLInfo.ToString();
}
}
}
2021年2月20日 星期六
OpenCV Trackbar
createTrackbar("Param1", "Window", &Param1, SliderMax, on_trackbar);
createTrackbar("Param2", "Window", &Param2, SliderMax, on_trackbar);#include <cstdio>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
const int SliderMax = 100;
int Param1 = 50;
int Param2 = 0;
Mat GrayImg, OutputImg;
static void on_trackbar(int, void*)
{
double Alpha = (float)Param1 / 50;
double Beta = Param2;
GrayImg.convertTo(OutputImg, -1, Alpha, Beta);
imshow("Window", OutputImg);
}
int main(){
Mat SrcImg = imread("dog.jpg", CV_LOAD_IMAGE_COLOR);
namedWindow("Window", WINDOW_AUTOSIZE);
cvtColor(SrcImg, GrayImg, CV_BGR2GRAY);
createTrackbar("Param1", "Window", &Param1, SliderMax, on_trackbar);
createTrackbar("Param2", "Window", &Param2, SliderMax, on_trackbar);
waitKey(0);
return 0;
}2020年12月31日 星期四
OpenCV findhomography(單應性矩陣)與warpperspective(透視變換)
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(){
Mat SrcImg1 = imread("SrcImg.jpg", CV_LOAD_IMAGE_COLOR);
Mat DstImg = Mat::zeros(Size(3500, 1500), CV_8SC1);
vector PtData1, PtData2;
PtData1.push_back(Point2f(513,627));
PtData1.push_back(Point2f(233, 2000));
PtData1.push_back(Point2f(3877, 2047));
PtData1.push_back(Point2f(3855, 835));
PtData2.push_back(Point2f(0, 0));
PtData2.push_back(Point2f(0, 1500));
PtData2.push_back(Point2f(3500, 1500));
PtData2.push_back(Point2f(3500, 0));
Mat HomogMat = findHomography(PtData1, PtData2, CV_RANSAC);
warpPerspective(SrcImg1, DstImg, HomogMat, DstImg.size());
imwrite(" DstImg.bmp", DstImg);
return 0;
} 2020年11月28日 星期六
Python with Anaconda and Visual Studio Code
2020年11月22日 星期日
OpenCV Image Watch
2020年10月25日 星期日
C++ 計算程式的執行時間
#include <opencv2/opencv.hpp>
#include "time.h"
using namespace cv;
using namespace std;
double StartTime, EndTime;
int main(){
//讀取影像
Mat SrcImg = imread("dog.jpg", CV_LOAD_IMAGE_COLOR);
Mat OutImg;
//紀錄起始時間點
StartTime = clock();
cvtColor(SrcImg, OutImg, CV_BGR2GRAY);
//紀錄結束時間點
EndTime = clock();
imshow("OutImg", OutImg);
waitKey(1000);
//因為clock回傳的都是ms,所以若要用s顯示則需要除CLOCKS_PER_SEC,CLOCKS_PER_SEC代表1000
//測試執行時間,通常都是以Ctrl+F5,則能得到最準確的時間
cout << " Time:" << (EndTime - StartTime) / CLOCKS_PER_SEC << "ms" << endl;
return 0;
}2020年9月27日 星期日
OpenCV Drawing Functions
這次來介紹OpenCV常用的六個畫圖函式,分別有畫線(line)、畫圓(circle)、畫矩形(rectangle)、畫橢圓(ellipse)、畫多邊形(polylines)、文字顯示(putText)等,說明如下:
--------------------------------------------------------------------------------------------------------------
1.line (InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
img:輸入影像
pt1:起點座標
pt1:終點座標
color:顏色
thickness:預設厚度為1
lineType:預設8連結,選項有LINE_4 (4連結)、LINE_8(8連結) 、LINE_AA (反鋸齒)
shift:預設座標小數點數為0
--------------------------------------------------------------------------------------------------------------
2.circle (InputOutputArray img, Point center, int radius, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
img:輸入影像
center:圓心座標
radius:半徑
color:顏色
thickness:預設厚度為1
lineType:預設8連結,選項有LINE_4 (4連結)、LINE_8(8連結) 、LINE_AA (反鋸齒)
shift:預設座標小數點數為0
--------------------------------------------------------------------------------------------------------------
3.rectangle (Mat &img, Rect rec, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
rectangle (InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
img:輸入影像
rect:矩形範圍(矩形左上角x座標,矩形左上角y座標,矩形寬度,矩形高度)
pt1:矩形左上角座標
pt2:矩形右下角座標
color:顏色
thickness:預設厚度為1
lineType:預設8連結,選項有LINE_4 (4連結)、LINE_8(8連結) 、LINE_AA (反鋸齒)
shift:預設座標小數點數為0
除此之外,如果想要繪製旋轉的矩形,則是定義RotateRect,並搭配line一條一條繪製,可參考下列程式碼
--------------------------------------------------------------------------------------------------------------
4.ellipse (InputOutputArray img, const RotatedRect &box, const Scalar &color, int thickness=1, int lineType=LINE_8)
ellipse (InputOutputArray img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
img:輸入影像
rotatedRect:旋轉矩形範圍(Point2f圓心座標, Size2f 矩形寬高,旋轉角度)
center:圓心座標
axes:橢圓長短軸長度的一半
angle:橢圓旋轉角度(請參考下圖,3.2.0版本圖片似乎是錯誤的,所以選3.3.0的圖片說明,註1)
startAngle:繪製起始角度(請參考下圖,註1)
endAngle:繪製結束角度(請參考下圖,註1)
color:顏色
thickness:預設厚度為1
lineType:預設8連結,選項有LINE_4 (4連結)、LINE_8(8連結) 、LINE_AA (反鋸齒)
shift:預設座標小數點數為0
--------------------------------------------------------------------------------------------------------------
5.polylines (InputOutputArray img, InputArrayOfArrays pts, bool isClosed, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
img:輸入影像
pts:點座標
isClosed:是否為封閉輪廓
color:顏色
thickness:預設厚度為1
lineType:預設8連結,選項有LINE_4 (4連結)、LINE_8(8連結) 、LINE_AA (反鋸齒)
shift:預設座標小數點數為0
--------------------------------------------------------------------------------------------------------------
6.putText (InputOutputArray img, const String &text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=LINE_8, bool bottomLeftOrigin=false)
img:輸入影像text:欲輸入文字內容
org:文字左下角座標
fontFace:文字類型(請參考下圖,註2)
fontScale:文字大小
color:顏色
thickness:預設厚度為1
lineType:預設8連結,選項有LINE_4 (4連結)、LINE_8(8連結) 、LINE_AA (反鋸齒)
shift:預設座標小數點數為0
--------------------------------------------------------------------------------------------------------------
程式碼如下:
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(){
Mat SrcImg(500, 500, CV_8UC3, Scalar(0, 0, 0));
Point StartPt = Point(25, 25), EndPt = Point(475, 475);
Point TextPt = Point(250, 65), CenterPt = Point(250, 250);
Size2f RotateSize = Size2f(200, 60);
int Thickness = 3;
//line function
line(SrcImg, StartPt, EndPt, Scalar(0, 255, 0), Thickness, 8, 0);
//circle function
circle(SrcImg, CenterPt, 30, Scalar(0, 255, 255), -1, 8, 0);
//rectangle function
Rect NormalRect = Rect(25, 25, 100, 100);
rectangle(SrcImg, NormalRect, Scalar(255, 0, 0), Thickness, 8, 0);
rectangle(SrcImg, Point(375, 375), EndPt, Scalar(255, 0, 0), Thickness, 8, 0);
//rotatedRect function
RotatedRect RotateRect = RotatedRect(CenterPt, RotateSize, 45);
Point2f Vertices[4];
RotateRect.points(Vertices);
for (int i = 0; i < 4; i++)
line(SrcImg, Vertices[i], Vertices[(i + 1) % 4], Scalar(255, 255, 0), Thickness, 8, 0);
//ellipse function
ellipse(SrcImg, CenterPt, Size(RotateSize.width / 2, RotateSize.height / 2), -45, 0, 360, Scalar(255, 0, 255), Thickness, 8, 0);
ellipse(SrcImg, RotateRect, Scalar(255, 0, 255), Thickness, 8);
//polylines function
vector polygons;
polygons.push_back(Point(25, 125));
polygons.push_back(Point(125, 125));
polygons.push_back(Point(125, 375));
polygons.push_back(Point(375, 375));
polygons.push_back(Point(375, 475));
polygons.push_back(Point(25, 475));
polylines(SrcImg, polygons, true, Scalar(255, 150, 150), Thickness, 8, 0);
//putText function
putText(SrcImg, "OpenCV", TextPt, FONT_HERSHEY_COMPLEX, 1.5, Scalar(0, 0, 255), Thickness, 8, false);
circle(SrcImg, TextPt, 1, Scalar(0, 0, 255), Thickness, 8, 0);
imshow("SrcImg", SrcImg);
waitKey(0);
return 0;
} 2020年9月14日 星期一
南投清境農場2日遊(小瑞士花園、高空步道、綿羊表演)
最近剛好有機會跟家人趁休假,規劃去南投清境玩,預定行程如下:
Day1
家->熱情果大本舖->小瑞士花園->櫻花步道->紙箱王->柳杉步道->飯店
Day2
飯店->清境農場->高空步道->綿羊表演->家
-------------------Go--------------------------------Go---------------
第一站
家->熱情果大本舖->小瑞士花園->櫻花步道->紙箱王->柳杉步道->飯店
純粹是想買百香果行程,因為埔里盛產水果之一就是百香果,且聽說有工廠提供遊客現場採百香果活動,有興趣的朋友們可以自己查查~ 這邊就不詳談了
第二站
家->熱情果大本舖->小瑞士花園->櫻花步道->紙箱王->柳杉步道->飯店
這邊建議可以先將車子停在清境第一停車場,因為小瑞士花園剛好就在旁邊,當然也可以直接停在小瑞士花園內的停車場,但感覺數量比較少
四處都有魚飼料販賣機,可以嘗試餵看看,會發現魚兒總是瘋狂的飛奔過來,不知道是餓了多久,哈哈
還有設置給情侶們專用的拍照區
第三站
家->熱情果大本舖->小瑞士花園->櫻花步道->紙箱王->柳杉步道->飯店
在前往紙箱王之前呢,跟大家快速說一下,在清境這邊有9條步道,各有各的特色,如果不想要上去又要一直找車位,可以考慮車子停在第一停車場,並用步行的方式走櫻花步道到紙箱王後,再經由柳杉步道回到停車場,此外,個人覺得步步高升步道很漂亮,但沒時間走到,下次有機會走看看。
不過因為櫻花步道走起來有點普通,所以在這邊就沒有特別放照片說明了~
到了紙箱王喔,在門口就會看到超多用紙箱做的藝術品,然後很多家庭會帶小朋友來逛
第四站
家->熱情果大本舖->小瑞士花園->櫻花步道->紙箱王->柳杉步道->飯店
第五站
家->熱情果大本舖->小瑞士花園->櫻花步道->紙箱王->柳杉步道->飯店
這次沒有刻意拍飯店的內容,所以就不多作介紹了~
馬上又是第二天的開始,今天就是直接殺去清境農場了
第一站
飯店->高空步道->清境農場->綿羊表演->家
這一天天氣算還不錯,但記得要擦防曬或準備放曬的衣物,免得回家變成小黑人,走在高空步道感覺真的很不錯,可以眺望遠方,彷彿可以摸到雲層般

















































