C++PythonC# 三语言OpenCV从零开发(7):图像的阈值

文章目录

  • 相关链接
  • 前言
  • 阈值
    • 阈值使用
      • 代码
        • Python
        • C++
        • Csharp
          • csharp代码问题
  • 总结

相关链接

C++&Python&Csharp in OpenCV 专栏

【2022B站最好的OpenCV课程推荐】OpenCV从入门到实战 全套课程(附带课程课件资料+课件笔记)

OpenCV一个窗口同时显示多张图片 (C++)

前言

我感觉我之前的比较实在是太过于偏代码了,缺少了图形学的知识的记录。之后的笔记我会把图形学的知识也记录上去。

阈值

阈值简单来说就是增强图片的对比。用过Ps的人就知道阈值是什么意思,在电脑绘画中用的还是比较多的

在这里插入图片描述

阈值使用

在这里插入图片描述

代码

Python
# %%
# 导入包
import cv2
import matplotlib.pyplot as plt
import numpy as np

image = {
    "image":'',
    "gray":'',
    
}

image["image"] = cv2.imread("D:/workSpace/OpenCV/HellOpenCV/Resources/image/cat.png")

# 获取颜色通道,因为cv2是BGR的顺序,所以这里是B 灰度
image["gray"]= cv2.split(image['image'])[0]

thresh = {
    '1' : '','2': '','3': '','4': '','5': ''
}

# 调用不同的阈值处理算子
ret , thresh['1'] = cv2.threshold(image['gray'],127,255,cv2.THRESH_BINARY)
ret , thresh['2'] = cv2.threshold(image['gray'],127,255,cv2.THRESH_BINARY_INV)
ret , thresh['3'] = cv2.threshold(image['gray'],127,255,cv2.THRESH_TRUNC)
ret , thresh['4'] = cv2.threshold(image['gray'],127,255,cv2.THRESH_TOZERO)
ret , thresh['5'] = cv2.threshold(image['gray'],127,255,cv2.THRESH_TOZERO_INV)

# 将数据总和成数组
titles = ['iamge','binary','binary inv','trunc','tozero','tozero inv']
images = [image['gray'],thresh['1'],thresh['2'],thresh['3'],thresh['4'],thresh['5']]

# 循环赋值到plt中
for i in range(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

plt.show()

在这里插入图片描述

C++

这里为了一次性展示多个窗口,我就CSDN上面找了个方法

OpenCV一个窗口同时显示多张图片 (C++)


#include <opencv2/opencv.hpp>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc.hpp>  
#include<iostream>  
#include <vector>
using namespace std;
using namespace cv;


vector<Mat> imageVector;

void multipleImage(vector<Mat> imgVector, Mat& dst, int imgCols)
{
	const int MAX_PIXEL = 300;
	int imgNum = imgVector.size();
	//选择图片最大的一边 将最大的边按比例变为300像素
	Size imgOriSize = imgVector[0].size();
	int imgMaxPixel = max(imgOriSize.height, imgOriSize.width);
	//获取最大像素变为MAX_PIXEL的比例因子
	double prop = imgMaxPixel < MAX_PIXEL ? (double)imgMaxPixel / MAX_PIXEL : MAX_PIXEL / (double)imgMaxPixel;
	Size imgStdSize(imgOriSize.width * prop, imgOriSize.height * prop); //窗口显示的标准图像的Size

	Mat imgStd; //标准图片
	Point2i location(0, 0); //坐标点(从0,0开始)
	//构建窗口大小 通道与imageVector[0]的通道一样
	Mat imgWindow(imgStdSize.height * ((imgNum - 1) / imgCols + 1), imgStdSize.width * imgCols, imgVector[0].type());
	for (int i = 0; i < imgNum; i++)
	{
		location.x = (i % imgCols) * imgStdSize.width;
		location.y = (i / imgCols) * imgStdSize.height;
		resize(imgVector[i], imgStd, imgStdSize, prop, prop, INTER_LINEAR); //设置为标准大小
		imgStd.copyTo(imgWindow(Rect(location, imgStdSize)));
	}
	dst = imgWindow;
}

int main()
{
	auto image = imread("D:/workSpace/OpenCV/HellOpenCV/Resources/image/cat.png");
	Mat showImage;

	Mat bgr[3];
	split(image, bgr);
	Mat gray = bgr[0];

	Mat thresh[5];

	threshold(gray, thresh[0], 127, 255, THRESH_BINARY);
	threshold(gray, thresh[1], 127, 255, THRESH_BINARY_INV);
	threshold(gray, thresh[2], 127, 255, THRESH_TRUNC);
	threshold(gray, thresh[3], 127, 255, THRESH_TOZERO);
	threshold(gray, thresh[4], 127, 255, THRESH_TOZERO_INV);


	vector<Mat> images{gray,thresh[0],thresh[1], thresh[2], thresh[3], thresh[4], };

	multipleImage(images, showImage, 3);

	imshow("C++", showImage);

	waitKey(0);
	destroyAllWindows();
	return 0;
}

在这里插入图片描述

Csharp

还是那句话,C++跑通了,Csharp抄抄就可以了。
在这里插入图片描述

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace HelloOpenCV.Utils
{
    public static class MyOpenCV_Extensions
    {

        /// <summary>
        /// 3通道遍历
        /// </summary>
        /// <param name="mat"></param>
        /// <returns></returns>
        public static int[,,] MatToArray(Mat mat)
        {

            var res = new int[mat.Rows, mat.Cols, mat.Channels()];
            for (var i = 0; i < mat.Rows; i++)
            {

                for (var j = 0; j < mat.Cols; j++)
                {
                    var temp = mat.At<Vec3b>(i, j);
                    res[i, j, 0] = temp[0];
                    res[i, j, 1] = temp[1];
                    res[i, j, 2] = temp[2];
                }
            }
            return res;
        }

        public static Mat MultipleImage(List<Mat> lists, int imgCols)
        {
            const int MAX_PIXEL = 300;
            int imgNum = lists.Count;
            //选择图片最大的一边 将最大的边按比例变为300像素
            Size imgOriSize = lists[0].Size();
            int imgMaxPixel = Math.Max(imgOriSize.Height, imgOriSize.Width);
            //获取最大像素变为MAX_PIXEL的比例因子
            double prop = imgMaxPixel < MAX_PIXEL ? (double)imgMaxPixel / MAX_PIXEL : MAX_PIXEL / (double)imgMaxPixel;
            Size imgStdSize= new Size(imgOriSize.Width* prop, imgOriSize.Height* prop); //窗口显示的标准图像的Size

            Mat imgStd = new Mat(); //标准图片
            
            Point location = new Point(0, 0); //坐标点(从0,0开始)
                                    //构建窗口大小 通道与imageVector[0]的通道一样
            Mat imgWindow = new Mat(imgStdSize.Height* ((imgNum -1) / imgCols + 1), imgStdSize.Width* imgCols, lists[0].Type());
            for (int i = 0; i < imgNum; i++)
            {
                location.X = (i % imgCols) * imgStdSize.Width;
                location.Y = (i / imgCols) * imgStdSize.Height;
                Cv2.Resize(lists[i], imgStd, imgStdSize, prop, prop, InterpolationFlags.Linear); //设置为标准大小
                imgStd.CopyTo(new Mat(imgWindow, new Rect(location, imgStdSize)) ); 
            }
            return imgWindow;
        }
    }
}

运行代码

 static void Main(string[] args)
 {
     Mat image = Cv2.ImRead("D:/workSpace/OpenCV/HellOpenCV/Resources/image/cat.png");

     Mat[] bgr = new Mat[3];
     Cv2.Split(image, out bgr);
     Mat gray = bgr[0];

     Mat[] threshs = new Mat[5];
     for(var i = 0; i < threshs.Length; i++)
     {
         threshs[i] = new Mat();
     }
     Cv2.Threshold(gray, threshs[0], 127, 255, ThresholdTypes.Binary);
     Cv2.Threshold(gray, threshs[1], 127, 255, ThresholdTypes.BinaryInv);
     Cv2.Threshold(gray, threshs[2], 127, 255, ThresholdTypes.Trunc);
     Cv2.Threshold(gray, threshs[3], 127, 255, ThresholdTypes.Tozero);
     Cv2.Threshold(gray, threshs[4], 127, 255, ThresholdTypes.TozeroInv);

     var res = MyOpenCV_Extensions.MultipleImage(new List<Mat>() {
         gray, threshs[0], threshs[1], threshs[2], threshs[3], threshs[4] 
     }, 3);


     Cv2.ImShow("Csharp", res);

     Cv2.WaitKey(0);
     Cv2.DestroyAllWindows();


 }

在这里插入图片描述

csharp代码问题

遇到了几个坑

C++是能直接把变量当做构造函数的,C# 对应的代码是构造函数里面带Mat参数的

在这里插入图片描述
在这里插入图片描述
而且C++的构造函数还不好定位,我进去找不到源码。我不知道C++ 的代码是怎么调试的,毕竟没怎么接触过

在这里插入图片描述

总结

跟之前的套路差不多,Python跑通,C++ 翻译Python+上网查资料,Csharp翻译C++。我还是觉得Csharp优雅多了,写起来舒服,C++ 这个语法用起来有点痛苦。而且C++ 报错天天给我报内存变量报错,我哪里能看得懂啊,顶多定位到哪行代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/357582.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

宋绪杰:我的大数据成长之旅 | 提升之路系列(三)

导读 为了发挥清华大学多学科优势&#xff0c;搭建跨学科交叉融合平台&#xff0c;创新跨学科交叉培养模式&#xff0c;培养具有大数据思维和应用创新的“π”型人才&#xff0c;由清华大学研究生院、清华大学大数据研究中心及相关院系共同设计组织的“清华大学大数据能力提升项…

SV-7102T网络播放解码器

SV-7102T是一款IP网络广播终端&#xff0c;具有10/100M以太网接口&#xff0c;其接收网络的音频数据&#xff0c;支持48KHz采样&#xff0c;192Kbps的音频流播放&#xff0c;并提供两路立体声15W的功率输出.SV-7102T设备只有网络广播功能&#xff0c;是一款简单的带功放输出的网…

Wireshark中的TCP协议包分析

Wireshark可以跟踪网络协议的通讯过程&#xff0c;本节通过TCP协议&#xff0c;在了解Wireshark使用的基础上&#xff0c;重温TCP协议的通讯过程。 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传…

如何使用手机安装JuiceSSH远程连接本地Linux服务器

⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 文章目录 ⛳️ 推荐1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址…

PAT-Apat甲级题1003(python和c++实现)下

PTA | 1003 Emergency 书接上回&#xff0c;上次我们使用了python实现无向带权图与DFS算法的设计&#xff0c;本次我们将使用C对本题进行解答&#xff0c;思路和题目分析同上一节内容&#xff0c;本次我们将在上一节的基础上继续实现。 okok现在又是激动人心的手搓代码时间&a…

MySQL解决 恢复从备份点到灾难点之间数据恢复

CSDN 成就一亿技术人&#xff01; 今天分享一期 mysql中 备份之后发生灾难造成数据丢失 那么如何恢复中间的数据呢&#xff1f; 数据库数据高于一切&#xff08;任何数据是不能丢失的&#xff09; CSDN 成就一亿技术人&#xff01; 目录 1.准备测试数据库 2.备份数据库 观…

Visual Studio 2022 C++ 生成dll或so文件在windows或linux下用C#调用

背景 开发中我们基本使用windows系统比较快捷&#xff0c;但是部署的时候我们又希望使用linux比较便宜&#xff0c;硬件产商还仅提供了c sdk&#xff01;苦了我们做二次开发的码农。 方案 需要确认一件事&#xff0c;目前c这门语言不是跨平台的 第一个问题【C生成dll在window…

C语言——深入理解指针1

目录 1. 内存和地址1.1 内存 2. 指针变量和地址2.1 取地址操作符2.2 指针变量和解引用操作符&#xff08;*&#xff09;2.2.1 指针变量2.2.2 如何拆解指针变量2.2.3 解引用操作符 2.3 指针的大小 3. 指针变量类型的意义3.1 指针的解引用3.2 指针 - 整数3.3 void*指针 4. const…

TypeScript 学习笔记(Day2)

「写在前面」 本文为 b 站黑马程序员 TypeScript 教程的学习笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。推荐先按顺序阅读往期内容&#xff1a; 1. TypeScript 学习笔记&#xff08;Day1&#xff09; 目录 3 TypeScript 常…

百度输入法往选字框里强塞广告

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 国内几乎100%的输入法都有广告&#xff0c;只是你们没发现而已&#xff01;&#xff01;&#xff01; 百度输入法居然在输入法键盘上推送广告&#xff0c;近日&#xff0c;博主阑夕 表示&#xff0c;V2EX论坛上有…

【webrtc】‘ninja.exe‘ 不是内部或外部命令,也不是可运行的程序及vs2019 重新构建m98

werbtc 就是用ninja.exe 来构建找到了自己以前构建的webrtc 原版 m98 【m98 】webrtc ninja 构建 、example、tests 及OWT- P2P 项目P2PMFC-E2E-m98G:\CDN\rtcCli\webrtc-checkout\src找到了自己的deptools的路径 deptools里确实没有ninja.exe D:\SOFT\depot_tools\third_party…

【LeetCode每日一题】56. 合并区间插入区间

一、判断区间是否重叠 力扣 252. 会议室 给定一个会议时间安排的数组 intervals &#xff0c;每个会议时间都会包括开始和结束的时间 intervals[i] [starti, endi] &#xff0c;请你判断一个人是否能够参加这里面的全部会议。 思路分析 因为一个人在同一时刻只能参加一个会…

《HTML 简易速速上手小册》第7章:HTML 多媒体与嵌入内容(2024 最新版)

文章目录 7.1 在HTML中嵌入视频和音频7.1.1 基础知识7.1.2 案例 1&#xff1a;嵌入视频文件7.1.3 案例 2&#xff1a;嵌入音频文件7.1.4 案例 3&#xff1a;创建一个视频和音频混合的播放列表 7.2 使用 <iframe> 嵌入外部内容7.2.1 基础知识7.2.2 案例 1&#xff1a;嵌入…

基于数字签名技术的挑战/响应式认证方式

挑战/响应式认证方式简便灵活&#xff0c;实现起来也比较容易。当网络需要验证用户身份时&#xff0c;客户端向服务器提出登录请求&#xff1b;当服务器接收到客户端的验证请求时&#xff0c;服务器端向客户端发送一个随机数&#xff0c;这就是这种认证方式的“冲击&#xff08…

ArcGIS Pro如何新建字段

无论是地图制作还是数据分析&#xff0c;字段的操作是必不可少的&#xff0c;在某些时候现有的字段不能满足需求还需要新建字段&#xff0c;这里为大家讲解一下在ArcGIS Pro中怎么新建字段&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的水…

响应式商业服务专利版权申请 公司网站模板源码系统 带完整的搭建教程

随着互联网的普及和发展&#xff0c;企业对于建立专业、高效的网站的需求日益增长。为了满足这一市场需求&#xff0c;罗峰给大家分享一款响应式商业服务专利版权申请公司网站模板源码系统。该系统不仅功能强大&#xff0c;而且易于搭建和定制&#xff0c;极大地降低了企业建立…

单片机学习笔记---定时器计数器(含寄存器)工作原理介绍(详解篇2)

目录 T1工作在方式2时 T0工作在方式3时 四种工作方式的总结 定时计数器对输入信号的要求 定时计数器对的编程的一个要求 关于初值计算的问题 4种工作方式的最大定时时间的大小 关于编程方式的问题 实例分析 实例1 实例2 T1工作在方式2时 51单片机&#xff0c;有两个…

python3.8 安装缺少ssl、_ctypes模块解决办法

问题 安装pyhton3.8安装默认不依赖ssl 运行Flask项目时报错&#xff1a; Traceback (most recent call last):File "/usr/local/python3/bin/flask", line 8, in <module>sys.exit(main())File "/usr/local/python3/lib/python3.8/site-packages/flask…

C语言递归篇章+系统讲解分析+深入理解递归+根源进行讲解+进制转换+操作环境+实例剖析+万字+百张图片精细化讲解

递归的讲解系统分析 什么是递归 本质上就是一种算法 最简单递归 栈溢出 没有限制条件 导致无穷尽的调用自己 从而溢出 最后变成死递归 _________________________________________________________________________________________________________________________________…

SAP MM 采购发票输入税额,模拟时候发现没有税科目记账税额!

原因&#xff1a;行项目税额和抬头不一样导致&#xff0c;以下是调整过的截图&#xff0c;原来底下是J2