图像直方图比较

对于直方图的比较,我们可以使用 OpenCV 提供的函数 compareHist() 进行比较,从而得到一个数值,表示两个直方图的匹配程度(相似性)。

原理

对于两个直方图( H 1 H_{1} H1 H 2 H_{2} H2),我们首先选用一个指标( d ( H 1 , H 2 ) d(H_{1}, H_{2}) d(H1,H2)),表示两个直方图的匹配度。

根据 Histogram Comparison 参考资料[1],OpenCV的 compareHist 函数计算直方图匹配度所提供的指标有以下4种:

  1. HISTCMP_CORREL:相关性
  2. HISTCMP_CHISQR:卡方
  3. HISTCMP_INTERSECT:交集
  4. HISTCMP_BHATTACHARYYA:巴氏距离

而根据 HistCompMethods[2],OpenCV的 compareHist 函数计算直方图匹配度所提供的指标有以下7种(实际为6种,巴氏和海林格算一种):

  1. HISTCMP_CORREL:相关性(Correlation)

    d ( H 1 , H 2 ) = ∑ I ( H 1 ( I ) − H 1 ˉ ) ( H 2 ( I ) − H 2 ˉ ) ∑ I ( H 1 ( I ) − H 1 ˉ ) 2 ∑ I ( H 2 ( I ) − H 2 ˉ ) 2 d(H_1,H_2) = \frac{\sum_I (H_1(I) - \bar{H_1}) (H_2(I) - \bar{H_2})}{\sqrt{\sum_I(H_1(I) - \bar{H_1})^2 \sum_I(H_2(I) - \bar{H_2})^2}} d(H1,H2)=I(H1(I)H1ˉ)2I(H2(I)H2ˉ)2 I(H1(I)H1ˉ)(H2(I)H2ˉ)

    其中,

    H 1 ˉ = 1 N ∑ I H 1 ( I ) \bar{H_1} = \frac{1}{N}\sum_I H_1(I) H1ˉ=N1IH1(I)

    N N N是直方图桶的数量。

  2. HISTCMP_CHISQR:卡方(Chi-Square)

    d ( H 1 , H 2 ) = ∑ I ( H 1 ( I ) − H 2 ( I ) ) 2 H 1 ( I ) d(H_1,H_2) = \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)} d(H1,H2)=IH1(I)(H1(I)H2(I))2

  3. HISTCMP_INTERSECT:交集(Intersection)

    d ( H 1 , H 2 ) = ∑ I min ⁡ ( H 1 ( I ) , H 2 ( I ) ) d(H_1,H_2) = \sum _I \min (H_1(I), H_2(I)) d(H1,H2)=Imin(H1(I),H2(I))

  4. HISTCMP_BHATTACHARYYA:巴氏距离(Bhattacharyya distance),事实上 OpenCV 计算的是与巴氏距离系数相关的海林格距离(Hellinger distance)。

    d ( H 1 , H 2 ) = 1 − 1 H 1 ˉ H 2 ˉ N 2 ∑ I H 1 ( I ) ⋅ H 2 ( I ) d(H_1,H_2) = \sqrt{1 - \frac{1}{\sqrt{\bar{H_1} \bar{H_2} N^2}} \sum_I \sqrt{H_1(I) \cdot H_2(I)}} d(H1,H2)=1H1ˉH2ˉN2 1IH1(I)H2(I)

  5. HISTCMP_HELLINGER:海林格距离(Hellinger distance),同巴氏距离。

  6. HISTCMP_CHISQR_ALT:修正卡方(Alternative Chi-Square)

    d ( H 1 , H 2 ) = 2 × ∑ I ( H 1 ( I ) − H 2 ( I ) ) 2 H 1 ( I ) + H 2 ( I ) d(H_1,H_2) = 2 × \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)+H_2(I)} d(H1,H2)=2×IH1(I)+H2(I)(H1(I)H2(I))2

    常被用于材质比较。

  7. HISTCMP_KL_DIV:库尔巴克-莱布勒散度(Kullback-Leibler divergence)

    d ( H 1 , H 2 ) = ∑ I H 1 ( I ) log ⁡ ( H 1 ( I ) H 2 ( I ) ) d(H_1,H_2) = \sum _I H_1(I) \log \left(\frac{H_1(I)}{H_2(I)}\right) d(H1,H2)=IH1(I)log(H2(I)H1(I))

OpenCV 中的声明与定义(以 4.10 版为例)

  • OpenCV 中 compareHist函数声明:

      /** @brief Compares two histograms.The function cv::compareHist compares two dense or two sparse histograms using the specified method.The function returns \f$d(H_1, H_2)\f$ .While the function works well with 1-, 2-, 3-dimensional dense histograms, it may not be suitablefor high-dimensional sparse histograms. In such histograms, because of aliasing and samplingproblems, the coordinates of non-zero histogram bins can slightly shift. To compare such histogramsor more general sparse configurations of weighted points, consider using the #EMD function.@param H1 First compared histogram.@param H2 Second compared histogram of the same size as H1 .@param method Comparison method, see #HistCompMethods*/CV_EXPORTS_W double compareHist( InputArray H1, InputArray H2, int method );/** @overload */CV_EXPORTS double compareHist( const SparseMat& H1, const SparseMat& H2, int method );
    
  • OpenCV 中 HistCompMethods 枚举:

      enum HistCompMethods {/** Correlation\f[d(H_1,H_2) =  \frac{\sum_I (H_1(I) - \bar{H_1}) (H_2(I) - \bar{H_2})}{\sqrt{\sum_I(H_1(I) - \bar{H_1})^2 \sum_I(H_2(I) - \bar{H_2})^2}}\f]where\f[\bar{H_k} =  \frac{1}{N} \sum _J H_k(J)\f]and \f$N\f$ is a total number of histogram bins. */HISTCMP_CORREL        = 0,/** Chi-Square\f[d(H_1,H_2) =  \sum _I  \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)}\f] */HISTCMP_CHISQR        = 1,/** Intersection\f[d(H_1,H_2) =  \sum _I  \min (H_1(I), H_2(I))\f] */HISTCMP_INTERSECT     = 2,/** Bhattacharyya distance(In fact, OpenCV computes Hellinger distance, which is related to Bhattacharyya coefficient.)\f[d(H_1,H_2) =  \sqrt{1 - \frac{1}{\sqrt{\bar{H_1} \bar{H_2} N^2}} \sum_I \sqrt{H_1(I) \cdot H_2(I)}}\f] */HISTCMP_BHATTACHARYYA = 3,HISTCMP_HELLINGER     = HISTCMP_BHATTACHARYYA, //!< Synonym for HISTCMP_BHATTACHARYYA/** Alternative Chi-Square\f[d(H_1,H_2) =  2 * \sum _I  \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)+H_2(I)}\f]This alternative formula is regularly used for texture comparison. See e.g. @cite Puzicha1997 */HISTCMP_CHISQR_ALT    = 4,/** Kullback-Leibler divergence\f[d(H_1,H_2) = \sum _I H_1(I) \log \left(\frac{H_1(I)}{H_2(I)}\right)\f] */HISTCMP_KL_DIV        = 5};
    
  • OpenCV 中 compareHist 函数定义:

// C O M P A R E   H I S T O G R A M S double cv::compareHist( InputArray _H1, InputArray _H2, int method )
{CV_INSTRUMENT_REGION();Mat H1 = _H1.getMat(), H2 = _H2.getMat();const Mat* arrays[] = {&H1, &H2, 0};Mat planes[2];NAryMatIterator it(arrays, planes);double result = 0;int j;CV_Assert( H1.type() == H2.type() && H1.depth() == CV_32F );double s1 = 0, s2 = 0, s11 = 0, s12 = 0, s22 = 0;CV_Assert( it.planes[0].isContinuous() && it.planes[1].isContinuous() );for( size_t i = 0; i < it.nplanes; i++, ++it ){const float* h1 = it.planes[0].ptr<float>();const float* h2 = it.planes[1].ptr<float>();const int len = it.planes[0].rows*it.planes[0].cols*H1.channels();j = 0;if( (method == CV_COMP_CHISQR) || (method == CV_COMP_CHISQR_ALT)){for( ; j < len; j++ ){double a = h1[j] - h2[j];double b = (method == CV_COMP_CHISQR) ? h1[j] : h1[j] + h2[j];if( fabs(b) > DBL_EPSILON )result += a*a/b;}}else if( method == CV_COMP_CORREL ){
#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F)v_float64 v_s1 = vx_setzero_f64();v_float64 v_s2 = vx_setzero_f64();v_float64 v_s11 = vx_setzero_f64();v_float64 v_s12 = vx_setzero_f64();v_float64 v_s22 = vx_setzero_f64();for ( ; j <= len - VTraits<v_float32>::vlanes(); j += VTraits<v_float32>::vlanes()){v_float32 v_a = vx_load(h1 + j);v_float32 v_b = vx_load(h2 + j);// 0-1v_float64 v_ad = v_cvt_f64(v_a);v_float64 v_bd = v_cvt_f64(v_b);v_s12 = v_muladd(v_ad, v_bd, v_s12);v_s11 = v_muladd(v_ad, v_ad, v_s11);v_s22 = v_muladd(v_bd, v_bd, v_s22);v_s1 = v_add(v_s1, v_ad);v_s2 = v_add(v_s2, v_bd);// 2-3v_ad = v_cvt_f64_high(v_a);v_bd = v_cvt_f64_high(v_b);v_s12 = v_muladd(v_ad, v_bd, v_s12);v_s11 = v_muladd(v_ad, v_ad, v_s11);v_s22 = v_muladd(v_bd, v_bd, v_s22);v_s1 = v_add(v_s1, v_ad);v_s2 = v_add(v_s2, v_bd);}s12 += v_reduce_sum(v_s12);s11 += v_reduce_sum(v_s11);s22 += v_reduce_sum(v_s22);s1 += v_reduce_sum(v_s1);s2 += v_reduce_sum(v_s2);
#elif CV_SIMD && 0 //Disable vectorization for CV_COMP_CORREL if f64 is unsupported due to low precisionv_float32 v_s1 = vx_setzero_f32();v_float32 v_s2 = vx_setzero_f32();v_float32 v_s11 = vx_setzero_f32();v_float32 v_s12 = vx_setzero_f32();v_float32 v_s22 = vx_setzero_f32();for (; j <= len - VTraits<v_float32>::vlanes(); j += VTraits<v_float32>::vlanes()){v_float32 v_a = vx_load(h1 + j);v_float32 v_b = vx_load(h2 + j);v_s12 = v_muladd(v_a, v_b, v_s12);v_s11 = v_muladd(v_a, v_a, v_s11);v_s22 = v_muladd(v_b, v_b, v_s22);v_s1 += v_a;v_s2 += v_b;}s12 += v_reduce_sum(v_s12);s11 += v_reduce_sum(v_s11);s22 += v_reduce_sum(v_s22);s1 += v_reduce_sum(v_s1);s2 += v_reduce_sum(v_s2);
#endiffor( ; j < len; j++ ){double a = h1[j];double b = h2[j];s12 += a*b;s1 += a;s11 += a*a;s2 += b;s22 += b*b;}}else if( method == CV_COMP_INTERSECT ){
#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F)v_float64 v_result = vx_setzero_f64();for ( ; j <= len - VTraits<v_float32>::vlanes(); j += VTraits<v_float32>::vlanes()){v_float32 v_src = v_min(vx_load(h1 + j), vx_load(h2 + j));v_result = v_add(v_result, v_add(v_cvt_f64(v_src), v_cvt_f64_high(v_src)));}result += v_reduce_sum(v_result);
#elif CV_SIMDv_float32 v_result = vx_setzero_f32();for (; j <= len - VTraits<v_float32>::vlanes(); j += VTraits<v_float32>::vlanes()){v_float32 v_src = v_min(vx_load(h1 + j), vx_load(h2 + j));v_result = v_add(v_result, v_src);}result += v_reduce_sum(v_result);
#endiffor( ; j < len; j++ )result += std::min(h1[j], h2[j]);}else if( method == CV_COMP_BHATTACHARYYA ){
#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F)v_float64 v_s1 = vx_setzero_f64();v_float64 v_s2 = vx_setzero_f64();v_float64 v_result = vx_setzero_f64();for ( ; j <= len - VTraits<v_float32>::vlanes(); j += VTraits<v_float32>::vlanes()){v_float32 v_a = vx_load(h1 + j);v_float32 v_b = vx_load(h2 + j);v_float64 v_ad = v_cvt_f64(v_a);v_float64 v_bd = v_cvt_f64(v_b);v_s1 = v_add(v_s1, v_ad);v_s2 = v_add(v_s2, v_bd);v_result = v_add(v_result, v_sqrt(v_mul(v_ad, v_bd)));v_ad = v_cvt_f64_high(v_a);v_bd = v_cvt_f64_high(v_b);v_s1 = v_add(v_s1, v_ad);v_s2 = v_add(v_s2, v_bd);v_result = v_add(v_result, v_sqrt(v_mul(v_ad, v_bd)));}s1 += v_reduce_sum(v_s1);s2 += v_reduce_sum(v_s2);result += v_reduce_sum(v_result);
#elif CV_SIMD && 0 //Disable vectorization for CV_COMP_BHATTACHARYYA if f64 is unsupported due to low precisionv_float32 v_s1 = vx_setzero_f32();v_float32 v_s2 = vx_setzero_f32();v_float32 v_result = vx_setzero_f32();for (; j <= len - VTraits<v_float32>::vlanes(); j += VTraits<v_float32>::vlanes()){v_float32 v_a = vx_load(h1 + j);v_float32 v_b = vx_load(h2 + j);v_s1 += v_a;v_s2 += v_b;v_result += v_sqrt(v_a * v_b);}s1 += v_reduce_sum(v_s1);s2 += v_reduce_sum(v_s2);result += v_reduce_sum(v_result);
#endiffor( ; j < len; j++ ){double a = h1[j];double b = h2[j];result += std::sqrt(a*b);s1 += a;s2 += b;}}else if( method == CV_COMP_KL_DIV ){for( ; j < len; j++ ){double p = h1[j];double q = h2[j];if( fabs(p) <= DBL_EPSILON ) {continue;}if(  fabs(q) <= DBL_EPSILON ) {q = 1e-10;}result += p * std::log( p / q );}}elseCV_Error( cv::Error::StsBadArg, "Unknown comparison method" );}if( method == CV_COMP_CHISQR_ALT )result *= 2;else if( method == CV_COMP_CORREL ){size_t total = H1.total();double scale = 1./total;double num = s12 - s1*s2*scale;double denom2 = (s11 - s1*s1*scale)*(s22 - s2*s2*scale);result = std::abs(denom2) > DBL_EPSILON ? num/std::sqrt(denom2) : 1.;}else if( method == CV_COMP_BHATTACHARYYA ){s1 *= s2;s1 = fabs(s1) > FLT_EPSILON ? 1./std::sqrt(s1) : 1.;result = std::sqrt(std::max(1. - result*s1, 0.));}return result;
}

应用示例

比较两个图像的灰度图匹配度。

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>using namespace cv;
using std::cout;
using std::endl;
using std::string;// 命令行参数
const char* keys ="{ help  h| | Print help message. }""{ @input1 |wukong1.jpg | Path to input image 1. }""{ @input2 |wukong2.jpg | Path to input image 2. }";const string CMP_METHODS[]{"Correlation", "Chi-Squared", "Intersection", "Bhattacharyya", "Hellinger", "Alternative Chi-Squared", "Kullback-Leibler Divergence"};int main(int argc, char** argv)
{// 命令行解析CommandLineParser parser(argc, argv, keys);// 加载图像Mat img1 = imread(parser.get<String>("@input1"));Mat img2 = imread(parser.get<String>("@input2"));// 检查图像是否加载成功if (img1.empty() || img2.empty()){cout << "Could not open or find the image!\n" << endl;cout << "Usage: " << argv[0] << " <Input_Image1> <Input_Image2>" << endl;parser.printMessage();return EXIT_FAILURE;}// 转换为灰度图Mat gray1, gray2;cvtColor(img1, gray1, COLOR_BGR2GRAY);cvtColor(img2, gray2, COLOR_BGR2GRAY);// 计算直方图int histSize = 256; // 256个灰度级,桶数// 灰度级范围float range[] = { 0, 256 };const float* histRange = { range };// 其它直方图计算参数bool uniform = true, accumulate = false;Mat hist1, hist2;calcHist(&gray1, 1, 0, Mat(), hist1, 1, &histSize, &histRange, uniform, accumulate);calcHist(&gray2, 1, 0, Mat(), hist2, 1, &histSize, &histRange, uniform, accumulate);// 归一化直方图normalize(hist1, hist1, 0, 1, NORM_MINMAX, -1, Mat());normalize(hist2, hist2, 0, 1, NORM_MINMAX, -1, Mat());// 比较直方图double correlation = compareHist(hist1, hist2, HISTCMP_CORREL);cout << "Similarity between the two images with " << CMP_METHODS[0] << ": " << correlation << endl;double chiSquared = compareHist(hist1, hist2, HISTCMP_CHISQR);cout << "Similarity between the two images with " << CMP_METHODS[1] << ": " << chiSquared << endl;double intersection = compareHist(hist1, hist2, HISTCMP_INTERSECT);cout << "Similarity between the two images with " << CMP_METHODS[2] << ": " << intersection << endl;double bhattacharyya = compareHist(hist1, hist2, HISTCMP_BHATTACHARYYA);cout << "Similarity between the two images with " << CMP_METHODS[3] << ": " << bhattacharyya << endl;double hellinger = compareHist(hist1, hist2, HISTCMP_HELLINGER);cout << "Similarity between the two images with " << CMP_METHODS[4] << ": " << hellinger << endl;double alternativeChiSquared = compareHist(hist1, hist2, HISTCMP_CHISQR_ALT);cout << "Similarity between the two images with " << CMP_METHODS[5] << ": " << alternativeChiSquared << endl;double kullbackLeibler = compareHist(hist1, hist2, HISTCMP_KL_DIV);cout << "Similarity between the two images with " << CMP_METHODS[6] << ": " << kullbackLeibler << endl;// 显示图像imshow("Image 1", img1);imshow("Image 2", img2);waitKey(0);return EXIT_SUCCESS;
}
import cv2
import numpy as np# 读取图像
image1_path = '../data/Histogram_Comparison_Source_0.jpg'
image2_path = '../data/Histogram_Comparison_Source_1.jpg'image1 = cv2.imread(image1_path)
image2 = cv2.imread(image2_path)# 转换为灰度图像
gray_image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
gray_image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)# 计算灰度图像的直方图
hist1 = cv2.calcHist([gray_image1], [0], None, [256], [0, 256])
hist2 = cv2.calcHist([gray_image2], [0], None, [256], [0, 256])# 归一化直方图
cv2.normalize(hist1, hist1, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
cv2.normalize(hist2, hist2, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)# 使用compareHist函数比较直方图
comparison_method = cv2.HISTCMP_CORREL  # 相关性比较方法
corr_similarity = cv2.compareHist(hist1, hist2, comparison_method)
chi_squared_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CHISQR)
intersection_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_INTERSECT)
bhattacharyya_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_BHATTACHARYYA)
hellinger_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_HELLINGER)
alternative_chi_squared_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CHISQR_ALT)
kbl_divergence_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_KL_DIV)print(f"Similarity between the two images with Correlation: {corr_similarity}")
print(f"Similarity between the two images with Chi-Squared: {chi_squared_similarity}")
print(f"Similarity between the two images with Intersection: {intersection_similarity}")
print(f"Similarity between the two images with Bhattacharyya: {bhattacharyya_similarity}")
print(f"Similarity between the two images with Hellinger: {hellinger_similarity}")
print(f"Similarity between the two images with Alternative Chi-Squared: {alternative_chi_squared_similarity}")
print(f"Similarity between the two images with Kullback-Leibler Divergence: {kbl_divergence_similarity}")# 显示结果
cv2.imshow('Image 1', image1)
cv2.imshow('Image 2', image2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Similarity between the two images with Correlation: 0.5185838942269291
Similarity between the two images with Chi-Squared: 53.894400613305585
Similarity between the two images with Intersection: 25.52862914837897
Similarity between the two images with Bhattacharyya: 0.358873990739656
Similarity between the two images with Hellinger: 0.358873990739656
Similarity between the two images with Alternative Chi-Squared: 34.90277478480459
Similarity between the two images with Kullback-Leibler Divergence: 71.12863163014705

参考资料

  1. Histogram Comparison
  2. HistCompMethods

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大数据】基础认知入门

目录 前言阅读对象阅读导航前置知识笔记正文一、什么是大数据1.1 定义1.2 特点1.3 数据结构1.4 补充总结 二、大数据能用来干什么2.1 应用方向2.2 应用场景&#xff08;简述&#xff09;2.3 总结 三、大数据一般性过程四、给自己的作业 感谢说在后面 前言 唉&#xff0c;最近有…

Kubectl命令、初识pod、namespace

文章目录 一、Kubectl简介基础命令1.基本信息命令2.创建和更新资源命令3.删除资源命令4. 查看日志和调试命令5. 端口转发和复制文件命令6. 部署管理命令7. 伸缩命令8. 配置和上下文管理命令9.常用命令 二、Pod简介核心概念pod常见状态调度和初始化阶段容器创建和运行阶段异常状…

Qt网络通信——TCP和UDP

一、TCP通信 TCP通信必须先建立 TCP 连接&#xff0c;通信端分为客户端和服务器端。 Qt 为服务器端提供了 QTcpServer 类用于实现端口监听&#xff0c;QTcpSocket 类则用于服务器和客户端之间建立连接。大致流程如下图所示&#xff1a; 1. 服务器端建立 1.1 监听——listen() …

PPP简介

介绍PPP特性的定义和目的。 定义 PPP&#xff08;Point-to-Point Protocol&#xff09;协议是一种点到点链路层协议&#xff0c;主要用于在全双工的同异步链路上进行点到点的数据传输。 目的 PPP协议是在串行线IP协议SLIP&#xff08;Serial Line Internet Protocol&#x…

【Android高级UI】将View或Layout裁剪为任意形状

需求 将View裁剪为指定形状 将Layout裁剪为指定形状&#xff0c;并且Children不能超过裁剪范围 应用 圆角图片异形图片圆角Layout 方案 通过ViewOutlineProvider裁剪控件范围 实现 fun View.getMeasureSize(): Size {val widthSpec View.MeasureSpec.makeMeasureSpec(…

代码随想录:动态规划6-10

62、不同路径 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径…

Hadoop入门基础(三):Hadoop启动踩坑记录

一、机器ssh连接方式非默认22端口 报错&#xff1a; sbin/start-dfs.sh Starting namenodes on [doop253] doop253: ssh: connect to host doop253 port 22: Connection refused 解决方法&#xff1a; sudo vim /etc/ssh/ssh_config 添加如下内容&#xff08;注意替换自己服…

[Qt] 避免CMake编译的Qt程序单独运行时出现控制台窗口的解决办法

只需要在add_executable中加上WIN32即可 避免CMake编译的Qt程序单独运行时出现控制台窗口的解决办法

史上最全的软件工厂考试简答题教程

软件工程考试简答题 1. 有人认为软件开发时&#xff0c;一个错误发现得越晚&#xff0c;为改正它所付出的代价越大。提出你的观点并解释原因&#xff1f; &#xff08;1&#xff09;在软件开发的不同阶段进行修改付出的代价是很不相同的&#xff0c;在早期引入变动&#xff0c…

【Harmony OS 4.0】交互事件(手势事件)

1. 绑定手势方法 1.1 gesture&#xff08;常规手势绑定方法&#xff09; 1.2 priorityGesture&#xff08;带优先级的手势绑定方法&#xff09; 1.3 parallelGesture&#xff08;并行手势绑定方法&#xff09; 可以在父子组件上绑定。可以同时响应的相同手势。当父组件绑定了…

如何清理win备用内存?备用内存过大怎么办?

下载这个软件RamMap 运行以后 选择Empty-Empty Standby List就行了 参考&#xff1a;https://www.zhihu.com/question/263768043 另外&#xff0c;禁用服务中的SystemMain&#xff0c;应该会停止占用备用内存&#xff0c;但是需要重启。 所以没办法只好创建一个任务计划&…

openai whisper使用

whisper使用 介绍 Whisper是一种通用的语音识别模型。它是在大量不同音频数据集上训练的&#xff0c;也是一个多任务模型&#xff0c;可以执行多语言语音识别、语音翻译和语言识别。 GitHub&#xff1a;https://github.com/openai/whisper 论文链接&#xff1a;https://arx…

注册Github账号详细过程

目录 一、准备工作 二、注册步骤 一、准备工作 在注册GitHub账号之前&#xff0c;请确保您已经准备好以下信息&#xff1a; 一个有效的电子邮箱地址&#xff1a;用于接收验证邮件和GitHub的后续通知。 用户名&#xff1a;确保该用户名在GitHub上是唯一的&#xff0c;且符合…

turtle画图知识

Turtle库是Python编程语言中的一个库&#xff0c;用于创建各种类型的图形&#xff0c;包括简单圆形、线条、路径和图片。它支持多种图形类型&#xff0c;并且可以绘制出各种复杂的形状。 以下是一些基本的使用方法&#xff1a; 1. 创建一个新的Turtle对象&#xff1a; pytho…

Leetcode JAVA刷刷站(53)最大子数组和

一、题目概述 二、思路方向 这个问题是一个经典的算法问题&#xff0c;称为“最大子序和”&#xff08;Maximum Subarray Problem&#xff09;。解决这个问题的一个高效方法是使用“Kadanes Algorithm”&#xff0c;它只需要遍历数组一次&#xff0c;就能在 O(n) 时间复杂度内…

CVPR2023《DNF: Decouple and Feedback Network for Seeing in the Dark》暗光图像增强论文阅读笔记

相关链接 论文链接 https://openaccess.thecvf.com/content/CVPR2023/papers/Jin_DNF_Decouple_and_Feedback_Network_for_Seeing_in_the_Dark_CVPR_2023_paper.pdf 代码链接 https://github.com/Srameo/DNF 摘要 RAW数据的独特属性在低光照图像增强方面展现出巨大潜力。…

C语言典型例题47

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题3.7 输入4个整数&#xff0c;要求按照从小到大的顺序输出 4个数之间进行比较&#xff0c;冒泡排序最最最详细过程&#xff0c;如果想更改为任意数之间相互比较&#xff0c;只需要修改两个地方&#xff08;数组大…

力扣面试经典算法150题:买卖股票的最佳时机 II

买卖股票的最佳时机 II 今天的题目是力扣面试经典150题中的数组的中等难度题&#xff1a;买卖股票的最佳时机 II。 题目链接&#xff1a;https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/?envTypestudy-plan-v2&envIdtop-interview-150 问…

教程:postman的平替hoppscotch,又叫postwoman,hoppscotch的docker-compose安装过程

目录 1. 背景2. 前期准备2.1 准备docker-compose文件&#xff0c;两个版本&#xff0c;一个3合1&#xff0c;一个分开2.1.1 3合1版本&#xff08;推荐&#xff09;2.1.2 独立版本 2.2 准备安装nginx-proxy-manager&#xff08;可选&#xff09;2.2 准备.env文件2.2.1 默认ip的.…

Spring Boot OAuth2.0应用

本文展示Spring Boot中&#xff0c;新版本OAuth2.0的简单实现&#xff0c;版本信息&#xff1a; spring-boot 2.7.10 spring-security-oauth2-authorization-server 0.4.0 spring-security-oauth2-client 5.7.7 spring-boot-starter-oauth2-resource-server 2.7.10展示三个服务…