数字图像处理(DIP)实验1 图像获取与直方图均衡化

数字图像处理(DIP)实验1 图像获取与直方图均衡化


数字图像处理课程相关文章 传送门

https://blog.csdn.net/qq_46164507/article/details/122503851


博文说明

本文所使用代码或多或少参考了以往博文的同类or相似文章的代码,并非纯原创
本文仅用于记录并提供一种代码思路,供大家参考



正文

要求

在这里插入图片描述

代码

运行环境:Ubuntu16.04 LTS + OpenCV 3.0.4 + ROS-kinetic-full

代码语言:c++

#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cv.h>
#include <highgui.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "ros/ros.h"
#define READIMAGE_ONLY
#ifndef READIMAGE_ONLY
#include <geometry_msgs/Twist.h>
#endif

using namespace cv;
using namespace std;


void openCVHist(const Mat src)
{
    //需要计算图像的哪个通道(bgr空间需要确定计算 b或g或r空间)
    const int channels[1] = {0};
    //直方图的每一个维度的 柱条的数目(就是将灰度级分组)
    int histSize[] = {256}; //如果这里写成int histSize = 256; 那么下面调用计算直方图的函数的时候,该变量需要写 &histSize
                            //定义一个变量用来存储 单个维度 的数值的取值范围
    float midRanges[] = {0, 256};
    //确定每个维度的取值范围,就是横坐标的总数
    const float *ranges[] = {midRanges};
    //输出的结果存储的 空间 ,用MatND类型来存储结果
    MatND dstHist;

    calcHist(&src, 1, channels, Mat(), dstHist, 1, histSize, ranges, true, false);
    //calcHist  函数调用结束后,dstHist变量中将储存了直方图的信息, 用dstHist的模版函数 at<Type>(i)得到第i个柱条的值  at<Type>(i, j)得到第i个并且第j个柱条的值
    //首先先创建一个黑底的图像,为了可以显示彩色,所以该绘制图像是一个8位的3通道图像
    Mat drawImage = Mat::zeros(Size(256, 256), CV_8UC3);

    //一个图像的某个灰度级的像素个数(最多为图像像素总数),可能会超过显示直方图的所定义的图像的尺寸,因此绘制直方图的时候,让直方图最高的地方只有图像高度的90%来显示
    //先用minMaxLoc函数来得到计算直方图后的像素的最大个数
    double g_dHistMaxValue;
    minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0);

    //遍历直方图得到的数据
    for (int i = 0; i < 256; i++)
    {
        int value = cvRound(256 * 0.9 * (dstHist.at<float>(i) / g_dHistMaxValue));
        line(drawImage, Point(i, drawImage.rows - 1), Point(i, drawImage.rows - 1 - value), Scalar(255, 0, 0));
    }
    imshow("OpenCVHist", drawImage);
    waitKey(0);
}



//直方图绘制函数,参数vector<int> nums 是灰度图片256级灰度的像素个数
void drawHist(string name,vector<int> nums)
{
    Mat hist = Mat::zeros(600, 800, CV_8UC3);
    vector<int>::iterator Max = max_element(nums.begin(), nums.end()-1); //max迭代器类型,最大数目
    putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255));
    //*********绘制坐标系************//
    Point o = Point(100, 550);
    Point x = Point(700, 550);
    Point y = Point(100, 150);
    //x轴
    line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0);
    //y轴
    line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0);

    //********绘制灰度曲线***********//
    Point pts[256];
    //生成坐标点
    for (int i = 0; i < 256; i++)
    {
        pts[i].x = i * 2 + 100;
        pts[i].y = 550 - int(nums[i] * (300.0 / (*Max))); //归一化到[0, 300]
        //显示横坐标
        if ((i + 1) % 16 == 0)
        {
            string num = format("%d", i + 1);
            putText(hist, num, Point(pts[i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
        }
    }
    //绘制线
    for (int i = 1; i < 256; i++)
    {
        line(hist, pts[i - 1], pts[i], Scalar(0, 255, 0), 2);
    }
    //显示图像
    imshow(name, hist);
}

void BalanceImage(vector<int> Nums, Mat Grey)
{
	vector<int> T(256);
	vector<int> result(256);
	int Total=0;
	int temp=0;
	for(int i=0;i!=256;i++)
	{
		Total+=Nums[i];
	}
	for(int i=0;i!=256;i++)
	{
		temp=temp+Nums[i];
		T[i]=int(255*((double)temp/(double)Total)+0.5);
	}
	for (int i = 0; i < Grey.rows; i++)
   {
        	//uchar *p = Grey.ptr<uchar>(i);
       for (int j = 0; j < Grey.cols; j++)
       {
          Grey.at<uchar>(i,j) = T[Grey.at<uchar>(i,j)];
          result[Grey.at<uchar>(i,j)]++;
      }
  }
  imshow("balanced_gray", Grey);
  drawHist("balanced_gray_hist",result);
  
}

//计算直方图,统计各灰度级像素个数
void calHist(Mat img)
{
    Mat grey;
    //读取图象
    //src = imread(img);
    if (!img.data)
    {
        cout << "Image读取失败" << endl;
        return;
    }
    //先转为灰度图
    cvtColor(img, grey, COLOR_BGR2GRAY);
    imshow("gray", grey);
    //计算各灰度级像素个数
    vector<int> nums(256);
    for (int i = 0; i < grey.rows; i++)
    {
        uchar *p = grey.ptr<uchar>(i);
        for (int j = 0; j < grey.cols; j++)
        {
            nums[p[j]]++;
        }
    }
    drawHist("gray_hist",nums);
    BalanceImage(nums,grey);
}


int main(int argc, char **argv)
{
	ROS_WARN("*****START*****");
	ros::init(argc, argv, "trafficLaneTrack"); //初始化ROS节点
	ros::NodeHandle n;

	//Before the use of camera, you can test ur program with images first: imread()
	VideoCapture capture;
	capture.open(0); //打开zed相机,如果要打开笔记本上的摄像头,需要改为0
	waitKey(100);
	if (!capture.isOpened())
	{
		printf("摄像头没有正常打开,重新插拔工控机上当摄像头\n");
		return 0;
	}

#ifndef READIMAGE_ONLY
	ros::Publisher pub = n.advertise<geometry_msgs::Twist>("/smoother_cmd_vel", 5); //定义dashgo机器人的速度发布器
#endif
	Mat src_frame;
	while (ros::ok())
	{
		capture.read(src_frame);
		if (src_frame.empty())
		{
			break;
		}
		// 此处为实验部分,请自行增加直方图均衡化的代码

		calHist(src_frame);

#ifndef READIMAGE_ONLY
		//以下代码可设置机器人的速度值,从而控制机器人运动
		geometry_msgs::Twist cmd_red;
		cmd_red.linear.x = 0;
		cmd_red.linear.y = 0;
		cmd_red.linear.z = 0;
		cmd_red.angular.x = 0;
		cmd_red.angular.y = 0;
		cmd_red.angular.z = 0.2;
		pub.publish(cmd_red);
#endif
		ros::spinOnce();
		waitKey(5);
	}
	return 0;
}


结果

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值