中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

寧夏做網(wǎng)站建設(shè)公司最新國際新聞10條

寧夏做網(wǎng)站建設(shè)公司,最新國際新聞10條,石家莊城鄉(xiāng)建設(shè)部網(wǎng)站首頁,織夢網(wǎng)站模板陶瓷基于OpenCV灰度圖像轉(zhuǎn)GCode的單向掃描實現(xiàn) 引言單向掃描存在的問題灰度圖像單向掃描代碼示例結(jié)論 系列文章 ?深入理解G0和G1指令:C中的實現(xiàn)與激光雕刻應用?基于二值化圖像轉(zhuǎn)GCode的單向掃描實現(xiàn)?基于二值化圖像轉(zhuǎn)GCode的雙向掃描實現(xiàn)?基于二值化圖像轉(zhuǎn)GCode的…
  • 基于OpenCV灰度圖像轉(zhuǎn)GCode的單向掃描實現(xiàn)
    • 引言
    • 單向掃描存在的問題
    • 灰度圖像單向掃描代碼示例
    • 結(jié)論

系列文章

  • ?深入理解G0和G1指令:C++中的實現(xiàn)與激光雕刻應用
  • ?基于二值化圖像轉(zhuǎn)GCode的單向掃描實現(xiàn)
  • ?基于二值化圖像轉(zhuǎn)GCode的雙向掃描實現(xiàn)
  • ?基于二值化圖像轉(zhuǎn)GCode的斜向掃描實現(xiàn)
  • ?基于二值化圖像轉(zhuǎn)GCode的螺旋掃描實現(xiàn)
  • ?基于OpenCV灰度圖像轉(zhuǎn)GCode的單向掃描實現(xiàn)
  • ?基于OpenCV灰度圖像轉(zhuǎn)GCode的雙向掃描實現(xiàn)
  • ?基于OpenCV灰度圖像轉(zhuǎn)GCode的斜向掃描實現(xiàn)
  • ?基于OpenCV灰度圖像轉(zhuǎn)GCode的螺旋掃描實現(xiàn)

?**系列文章GitHub倉庫地址**

基于OpenCV灰度圖像轉(zhuǎn)GCode的單向掃描實現(xiàn)

本文將介紹如何使用OpenCV庫將灰度圖轉(zhuǎn)換為GCode,并通過單向掃描實現(xiàn)對圖像的激光雕刻。GCode是一種用于控制數(shù)控機床和3D打印機的指令語言,而OpenCV是一種開源計算機視覺庫。通過結(jié)合這兩者,我們可以實現(xiàn)從圖像到GCode的轉(zhuǎn)換,進而在機器上實現(xiàn)圖像的物理輸出。

引言

在數(shù)字制造時代,將圖像轉(zhuǎn)換為GCode是實現(xiàn)自動化加工和打印的關(guān)鍵步驟。本文將探討如何利用OpenCV庫將灰度圖轉(zhuǎn)換為GCode,并通過單向掃描的方式實現(xiàn)對圖像的激光雕刻。
未優(yōu)化的單向掃描
上圖是未做任何處理,直接從灰度圖轉(zhuǎn)換成GCode。
已優(yōu)化的單向掃描
優(yōu)化后生成的GCode如上所示:
原始圖像
原始圖像如上所示:

單向掃描存在的問題

單向操作存在來回折返空行程問題,導致加工時間變長。
本文主要通過使用以下形式的代碼,刪除了多余的行程(空跑沒任何意義的G0)。

while(++x < image.cols && image.at<std::uint8_t>(y, x) == 255) {length++;
}
--x;

實現(xiàn)了未優(yōu)化版本和優(yōu)化版本的單向掃描,兩者加工時間從生成的GCode代碼上,可以看出有了很大差異。

紅色是 G0,綠色是加工部分 G1。

當然如果使用雙向掃描方向,加工時間差異會更大。

灰度圖像單向掃描代碼示例

編譯器要求最低 C++23

#pragma once
#include <opencv2/opencv.hpp>
#include <fstream>
#include <print>
#include <vector>
#include <optional>
#include <ranges>struct G0 {std::optional<float> x, y;std::optional<int> s;std::string toString() {std::string command = "G0";if(x.has_value()) {command += std::format(" X{:.3f}", x.value());}if(y.has_value()) {command += std::format(" Y{:.3f}", y.value());}if(s.has_value()) {command += std::format(" S{:d}", s.value());}return command;}explicit  operator std::string() const {std::string command = "G0";if(x.has_value()) {command += std::format(" X{:.3f}", x.value());}if(y.has_value()) {command += std::format(" Y{:.3f}", y.value());}if(s.has_value()) {command += std::format(" S{:d}", s.value());}return command;}
};struct G1 {std::optional<float> x, y;std::optional<int> s;std::string toString() {std::string command = "G1";if(x.has_value()) {command += std::format(" X{:.3f}", x.value());}if(y.has_value()) {command += std::format(" Y{:.3f}", y.value());}if(s.has_value()) {command += std::format(" S{:d}", s.value());}return command;}explicit operator std::string() const {std::string command = "G1";if(x.has_value()) {command += std::format(" X{:.3f}", x.value());}if(y.has_value()) {command += std::format(" Y{:.3f}", y.value());}if(s.has_value()) {command += std::format(" S{:d}", s.value());}return command;}
};class ImageToGCode
{
public:// 激光模式enum class LaserMode {Cutting,    // 切割 M3 Constant PowerEngraving,  // 雕刻 M4 Dynamic Power};// 掃描方式enum class ScanMode {Unidirection,  // 單向Bidirection,   // 雙向};struct kEnumToStringLaserMode {constexpr std::string_view operator[](const LaserMode mode) const noexcept {switch(mode) {case LaserMode::Cutting: return "M3";case LaserMode::Engraving: return "M4";}return {};}constexpr LaserMode operator[](const std::string_view mode) const noexcept {if(mode.compare("M3")) {return LaserMode::Cutting;}if(mode.compare("M4")) {return LaserMode::Engraving;}return {};}};ImageToGCode() = default;~ImageToGCode() = default;auto &setInputImage(const cv::Mat &mat) {this->mat = mat;return *this;}auto &setOutputTragetSize(double width, double height, double resolution = 10.0 /* lin/mm */) {this->width      = width;this->height     = height;this->resolution = resolution;return *this;}auto &builder() {command.clear();try {matToGCode();} catch(cv::Exception &e) {std::println("cv Exception {}", e.what());}std::vector<std::string> header;header.emplace_back("G17G21G90G54");                                             // XY平面;單位毫米;絕對坐標模式;選擇G54坐標系header.emplace_back(std::format("F{:d}", 30000));                                // 移動速度 毫米/每分鐘header.emplace_back(std::format("G0 X{:.3f} Y{:.3f}", 0.f, 0.f));                // 設(shè)置工作起點及偏移header.emplace_back(std::format("{} S0", kEnumToStringLaserMode()[laserMode]));  // 激光模式if(airPump.has_value()) {header.emplace_back(std::format("M16 S{:d}", 300));  // 打開氣泵}std::vector<std::string> footer;footer.emplace_back("M5");if(airPump.has_value()) {footer.emplace_back("M9");  // 關(guān)閉氣泵,保持 S300 功率}command.insert_range(command.begin(), header);command.append_range(footer);return *this;}bool exportGCode(const std::string &fileName) {std::fstream file;file.open(fileName, std::ios_base::out | std::ios_base::trunc);if(!file.is_open()) {return false;}for(auto &&v: command | std::views::transform([](auto item) { return item += "\n"; })) {file.write(v.c_str(), v.length());}return true;}auto setLaserMode(LaserMode mode) {laserMode = mode;return *this;}auto setScanMode(ScanMode mode) {scanMode = mode;return *this;}private:void matToGCode() {assert(mat.channels() == 1);assert(std::isgreaterequal(resolution, 1e-5f));assert(!((width * resolution < 1.0) || (height * resolution < 1.0)));unidirectionStrategy();}void internal(cv::Mat &image, auto x /*width*/, auto y /*height*/) {auto pixel = image.at<cv::uint8_t>(y, x);if(pixel == 255) {command.emplace_back(G0(x / resolution, y / resolution, std::nullopt));} else {auto power = static_cast<int>((1.0 - static_cast<double>(pixel) / 255.0) * 1000.0);command.emplace_back(G1(x / resolution, y / resolution, power));}}// 單向掃描// 未做任何優(yōu)化處理,像素和G0、G1一一映射對應。void unidirectionStrategy() {cv::Mat image;cv::resize(mat, image, cv::Size(static_cast<int>(width * resolution), static_cast<int>(height * resolution)));cv::imshow("mat",image);cv::waitKey(0);for(int y = 0; y < image.rows; ++y) {command.emplace_back(G0(0, y / resolution, std::nullopt).toString());for(int x = 0; x < image.cols; ++x) {auto pixel = image.at<uchar>(y, x);if(pixel == 255) {command.emplace_back(G0(x / resolution, std::nullopt, std::nullopt));} else {auto power = static_cast<int>((1.0 - static_cast<double>(pixel) / 255.0) * 1000.0);command.emplace_back(G1(x / resolution, std::nullopt, power));}}}}// 單向掃描優(yōu)化版本V1// 刪除多余空行程,這里空行程指連續(xù)的無用的G0。void unidirectionOptStrategy() {cv::Mat image;cv::resize(mat, image, cv::Size(static_cast<int>(width * resolution), static_cast<int>(height * resolution)));int offset = 0;  // The frist consecutive G0int length = 0;for(int y = 0; y < image.rows; ++y) {command.emplace_back(G0(offset / resolution, y / resolution, std::nullopt).toString());for(int x = 0; x < image.cols; ++x) {auto pixel = image.at<uchar>(y, x);length     = 0;if(pixel == 255) {while(++x < image.cols && image.at<std::uint8_t>(y, x) == 255) {length++;}--x;// Whether continuous GO existsif(length) {if(x - length == 0) {  // skip The frist consecutive G0offset = length;command.emplace_back(G0((x) / resolution, std::nullopt, std::nullopt));continue;}if(x == image.cols - 1) {  // skip The last consecutive G0command.emplace_back(G0((x - length) / resolution, std::nullopt, std::nullopt));continue;}// Continuous GOcommand.emplace_back(G0(x / resolution, std::nullopt, std::nullopt));} else {// Independent GOcommand.emplace_back(G0(x / resolution, std::nullopt, std::nullopt));}} else {auto power = static_cast<int>((1.0 - static_cast<double>(pixel) / 255.0) * 1000.0);command.emplace_back(G1(x / resolution, std::nullopt, power));}}}}// Define additional strategy functions here
private:cv::Mat mat;                                 // 灰度圖像double width {0};                            // 工作范圍 x 軸double height {0};                           // 工作范圍 y 軸double resolution {0};                       // 精度 lin/mmScanMode scanMode {ScanMode::Bidirection};   // 默認雙向LaserMode laserMode {LaserMode::Engraving};  // 默認雕刻模式std::optional<int> airPump;                  // 自定義指令 氣泵 用于吹走加工產(chǎn)生的灰塵 范圍 [0,1000]// add more custom cmdstd::vector<std::string> command;            // G 代碼
};int main() {// 讀取以灰度的形式讀取一個圖像cv::Mat mat = cv::imread(R"(ImageToGCode\image\tigger.jpg)", cv::IMREAD_GRAYSCALE);cv::flip(mat, mat, 0);// 實例化一個對象ImageToGCode handle;// 設(shè)置相關(guān)參數(shù)// setInputImage 輸入圖像// setOutputTragetSize 輸出物理尺寸大小 以 mm 為單位,這里輸出 50x50 mm 大小// builder 開始執(zhí)行圖像轉(zhuǎn)GCode操作// exportGCode 導出 gcode 文件handle.setInputImage(mat).setOutputTragetSize(50,50).builder().exportGCode(R"(ImageToGCode\output\001.nc)");
}

結(jié)論

通過結(jié)合OpenCV和GCode,我們成功地將灰度圖轉(zhuǎn)換為機器可執(zhí)行的指令,實現(xiàn)了對圖像的單向掃描激光雕刻。這種方法可應用于數(shù)控機床和3D打印機等領(lǐng)域,為數(shù)字制造提供了更靈活的圖像處理和加工方式。

http://www.risenshineclean.com/news/12009.html

相關(guān)文章:

  • 國外好的做電視包裝的網(wǎng)站鏈接轉(zhuǎn)二維碼
  • 豬八戒網(wǎng)做網(wǎng)站怎么樣今日新聞快報
  • 哪個網(wǎng)站做外貿(mào)好互聯(lián)網(wǎng)營銷師
  • 長沙自助模板建站百度官方免費下載安裝
  • 交易網(wǎng)站建設(shè)電商營銷策劃方案
  • 泉州公司做網(wǎng)站服裝品牌營銷策劃方案
  • 岳陽seo官網(wǎng)廣東百度seo關(guān)鍵詞排名
  • 中國建設(shè)銀行網(wǎng)站首頁u盾登入百度推廣基木魚
  • 蘇州高端網(wǎng)站設(shè)計企業(yè)滕州今日頭條新聞
  • 網(wǎng)站頁面怎么設(shè)計寧夏百度推廣代理商
  • 東麗區(qū) 網(wǎng)站建設(shè)今日足球賽事數(shù)據(jù)
  • 鄭州營銷網(wǎng)站托管seo最新技巧
  • 微網(wǎng)站促銷版seo輔助工具
  • 做劇情網(wǎng)站侵權(quán)嗎簡述網(wǎng)絡(luò)營銷的方法
  • 去年做那個網(wǎng)站致富google官網(wǎng)注冊賬號入口
  • 環(huán)保設(shè)備網(wǎng)站怎么做手機百度云電腦版入口
  • 設(shè)計網(wǎng)站要多久東莞seo技術(shù)培訓
  • 團隊云智能網(wǎng)站建設(shè)crm
  • 以下屬于b2c網(wǎng)站的是搜索引擎廣告形式有
  • 西安買公司的網(wǎng)站建設(shè)百度一下百度下載
  • 互聯(lián)網(wǎng)網(wǎng)站建設(shè)哪里好新聞播報最新
  • 工業(yè)產(chǎn)品設(shè)計與創(chuàng)客實踐技能大賽蘋果aso優(yōu)化
  • 買什么樣的主機(用來建網(wǎng)站的)支持下載免費網(wǎng)站制作軟件平臺
  • 站群子網(wǎng)站開發(fā)小程序開發(fā)平臺
  • 網(wǎng)站建設(shè)合作范本橙子建站官網(wǎng)
  • 手游代理平臺哪個好seo專員是什么
  • 做外貿(mào)批發(fā)的網(wǎng)站有哪些seo搜索引擎優(yōu)化實訓
  • dedecms農(nóng)業(yè)種植網(wǎng)站模板蘇州seo關(guān)鍵詞優(yōu)化方法
  • 廈門網(wǎng)站建設(shè)公司新網(wǎng)域名
  • 中國能建官網(wǎng)seo短視頻網(wǎng)頁入口引流免費