开发者社区> 流楚丶格念> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

opencv测试

简介: opencv测试
+关注继续查看
#include<iostream>
#include<string.h>
#include<math.h>
#include<vector>
#include<opencv2/core/core.hpp>
#include<opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include "opencv2/ml.hpp"
#include "opencv2/objdetect.hpp"
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2\imgproc\imgproc_c.h>
#include<opencv2\highgui\highgui.hpp>
#include "opencv2/highgui/highgui.hpp"



using namespace std;
using namespace cv;


void swap(int& x, int& y)
{
 int temp;
 temp = x;
 x = y;
 y = temp;

}

// 去噪匹配
int searchmedia(int *arr, int length)
{
 int i, j;
 for (i = 0; i < length - 1; i++)
     for (j = 0; j < length - i - 1; j++)
     {
         if (arr[j] > arr[j + 1])
             swap(arr[j], arr[j + 1]);
     }

 return arr[4];

}


// 中值滤波去噪处理
void MediaFilter(Mat& Saltimg, Mat& _dst)
{
 Mat dst = Mat(Saltimg.size(), Saltimg.type());
 int arr[9];
 // channels()返回矩阵通道的数量。
 if (dst.channels() == 3)
 {
     for (int i = 0; i < dst.rows; i++)
         for (int j = 0; j < dst.cols; j++)
         {
             if (i - 1 > 0 && j - 1 > 0 && i < dst.rows - 1 && j < dst.cols - 1)
             {
                 arr[0] = Saltimg.at<Vec3b>(i - 1, j - 1)[0];
                 arr[1] = Saltimg.at<Vec3b>(i - 1, j)[0];
                 arr[2] = Saltimg.at<Vec3b>(i - 1, j + 1)[0];
                 arr[3] = Saltimg.at<Vec3b>(i, j - 1)[0];
                 arr[4] = Saltimg.at<Vec3b>(i, j)[0];
                 arr[5] = Saltimg.at<Vec3b>(i, j + 1)[0];
                 arr[6] = Saltimg.at<Vec3b>(i + 1, j - 1)[0];
                 arr[7] = Saltimg.at<Vec3b>(i + 1, j)[0];
                 arr[8] = Saltimg.at<Vec3b>(i + 1, j + 1)[0];
                 dst.at<Vec3b>(i, j)[0] = searchmedia(arr, 9);

                 arr[0] = Saltimg.at<Vec3b>(i - 1, j - 1)[1];
                 arr[1] = Saltimg.at<Vec3b>(i - 1, j)[1];
                 arr[2] = Saltimg.at<Vec3b>(i - 1, j + 1)[1];
                 arr[3] = Saltimg.at<Vec3b>(i, j - 1)[1];
                 arr[4] = Saltimg.at<Vec3b>(i, j)[1];
                 arr[5] = Saltimg.at<Vec3b>(i, j + 1)[1];
                 arr[6] = Saltimg.at<Vec3b>(i + 1, j - 1)[1];
                 arr[7] = Saltimg.at<Vec3b>(i + 1, j)[1];
                 arr[8] = Saltimg.at<Vec3b>(i + 1, j + 1)[1];
                 dst.at<Vec3b>(i, j)[1] = searchmedia(arr, 9);

                 arr[0] = Saltimg.at<Vec3b>(i - 1, j - 1)[2];
                 arr[1] = Saltimg.at<Vec3b>(i - 1, j)[2];
                 arr[2] = Saltimg.at<Vec3b>(i - 1, j + 1)[2];
                 arr[3] = Saltimg.at<Vec3b>(i, j - 1)[2];
                 arr[4] = Saltimg.at<Vec3b>(i, j)[2];
                 arr[5] = Saltimg.at<Vec3b>(i, j + 1)[2];
                 arr[6] = Saltimg.at<Vec3b>(i + 1, j - 1)[2];
                 arr[7] = Saltimg.at<Vec3b>(i + 1, j)[2];
                 arr[8] = Saltimg.at<Vec3b>(i + 1, j + 1)[2];
                 dst.at<Vec3b>(i, j)[2] = searchmedia(arr, 9);

             }
             else
             {
                 dst.at<Vec3b>(i, j)[0] = Saltimg.at<Vec3b>(i, j)[0];
                 dst.at<Vec3b>(i, j)[1] = Saltimg.at<Vec3b>(i, j)[1];
                 dst.at<Vec3b>(i, j)[2] = Saltimg.at<Vec3b>(i, j)[2];
             }
         }
 }
 else if (dst.channels() == 1)
 {
     for (int i = 0; i < dst.rows; i++)
         for (int j = 0; j < dst.cols; j++)
         {
             if (i - 1 > 0 && j - 1 > 0 && i < dst.rows - 1 && j < dst.cols - 1)
             {

                 arr[0] = Saltimg.at<uchar>(i - 1, j - 1);
                 arr[1] = Saltimg.at<uchar>(i - 1, j);
                 arr[2] = Saltimg.at<uchar>(i - 1, j + 1);
                 arr[3] = Saltimg.at<uchar>(i, j - 1);
                 arr[4] = Saltimg.at<uchar>(i, j);
                 arr[5] = Saltimg.at<uchar>(i, j + 1);
                 arr[6] = Saltimg.at<uchar>(i + 1, j - 1);
                 arr[7] = Saltimg.at<uchar>(i + 1, j);
                 arr[8] = Saltimg.at<uchar>(i + 1, j + 1);
                 dst.at<uchar>(i, j) = searchmedia(arr, 9);
             }

             else
             {
                 dst.at<uchar>(i, j) = Saltimg.at<uchar>(i, j);
             }

         }


 }
 dst.copyTo(_dst);

}

int gray[256] = { 0 };  //记录每个灰度级别下的像素个数
double gray_prob[256] = { 0 };  //记录灰度分布密度
double gray_distribution[256] = { 0 };  //记录累计密度
int gray_equal[256] = { 0 };  //均衡化后的灰度值

int gray_sum = 0;  //像素总数

Mat equalize_hist(Mat& input)
{
 Mat output = input.clone();
 gray_sum = input.cols * input.rows;

 //统计每个灰度下的像素个数
 for (int i = 0; i < input.rows; i++)
 {
     uchar* p = input.ptr<uchar>(i);
     for (int j = 0; j < input.cols; j++)
     {
         int vaule = p[j];
         gray[vaule]++;
     }
 }


 //统计灰度频率
 for (int i = 0; i < 256; i++)
 {
     gray_prob[i] = ((double)gray[i] / gray_sum);
 }

 //计算累计密度
 gray_distribution[0] = gray_prob[0];
 for (int i = 1; i < 256; i++)
 {
     gray_distribution[i] = gray_distribution[i - 1] + gray_prob[i];
 }

 //重新计算均衡化后的灰度值,四舍五入。参考公式:(N-1)*T+0.5
 for (int i = 0; i < 256; i++)
 {
     gray_equal[i] = (uchar)(255 * gray_distribution[i] + 0.5);
 }


 //直方图均衡化,更新原图每个点的像素值
 for (int i = 0; i < output.rows; i++)
 {
     uchar* p = output.ptr<uchar>(i);
     for (int j = 0; j < output.cols; j++)
     {
         p[j] = gray_equal[p[j]];
     }
 }

 return output;
}

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

 calcHist(&img, 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);
 //因为任何一个图像的某个像素的总个数,都有可能会有很多,会超出所定义的图像的尺寸,针对这种情况,先对个数进行范围的限制  
 //先用 minMaxLoc函数来得到计算直方图后的像素的最大个数  
 double g_dHistMaxValue;
 minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0);
 //将像素的个数整合到 图像的最大范围内  
 //遍历直方图得到的数据  
 for (int i = 0; i < 256; i++)
 {
     int value = cvRound(dstHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue);

     line(drawImage, Point(i, drawImage.rows - 1), Point(i, drawImage.rows - 1 - value), Scalar(255, 255, 255));
 }
 namedWindow("直方图",WINDOW_AUTOSIZE);
 imshow("直方图", drawImage);
}

int DetectThreshold(Mat *src)
{
 uchar iThrehold;//阀值

 try
 {
     int height = src->cols; 
     int width = src->rows;
     int step = src->rows / sizeof(uchar);
     uchar *data = src->data;

     cout << src->cols << endl
         << src->rows<<endl;

     int iDiffRec = 0;
     int F[256] = { 0 }; //直方图数组  
     int iTotalGray = 0;//灰度值和  
     int iTotalPixel = 0;//像素数和  
     uchar bt;//某点的像素值  

     uchar iNewThrehold;//新阀值
     uchar iMaxGrayValue = 0, iMinGrayValue = 255;//原图像中的最大灰度值和最小灰度值  
     uchar iMeanGrayValue1, iMeanGrayValue2;

     //获取(i,j)的值,存于直方图数组F  
     for (int i = 0; i < width; i++)
     {
         for (int j = 0; j < height; j++)
         {
             bt = data[i*step + j];
             if (bt < iMinGrayValue)
                 iMinGrayValue = bt;
             if (bt > iMaxGrayValue)
                 iMaxGrayValue = bt;
             F[bt]++;
         }
     }

     iThrehold = 0;
     iNewThrehold = (iMinGrayValue + iMaxGrayValue) / 2;//初始阀值  
     iDiffRec = iMaxGrayValue - iMinGrayValue;

     for (int a = 0; (abs(iThrehold - iNewThrehold) > 0.5); a++)//迭代中止条件  
     {
         iThrehold = iNewThrehold;
         //小于当前阀值部分的平均灰度值  
         for (int i = iMinGrayValue; i < iThrehold; i++)
         {
             iTotalGray += F[i] * i;//F[]存储图像信息  
             iTotalPixel += F[i];
         }
         iMeanGrayValue1 = (uchar)(iTotalGray / iTotalPixel);
         //大于当前阀值部分的平均灰度值  
         iTotalPixel = 0;
         iTotalGray = 0;
         for (int j = iThrehold + 1; j < iMaxGrayValue; j++)
         {
             iTotalGray += F[j] * j;//F[]存储图像信息  
             iTotalPixel += F[j];
         }
         iMeanGrayValue2 = (uchar)(iTotalGray / iTotalPixel);

         iNewThrehold = (iMeanGrayValue2 + iMeanGrayValue1) / 2; //新阀值  
         iDiffRec = abs(iMeanGrayValue2 - iMeanGrayValue1);
     }
 }
 catch (cv::Exception e)
 {
 }

 return iThrehold;
}


//度数转换
double degreeTurn(double theta)
{
 double finaldegree = theta / CV_PI * 180;
 return finaldegree;
}

//逆时针旋转图像degree角度(原尺寸) 
void rotateImage(Mat Img, Mat& rotateImg, double degree)
{
 //旋转中心为图像中心 
 Point2f center;
 center.x = float(Img.cols / 2.0);
 center.y = float(Img.rows / 2.0);
 int length = 0;
 length = sqrt(Img.cols * Img.cols + Img.rows * Img.rows);
 Mat matrix = getRotationMatrix2D(center, degree, 1);//仿射变换矩阵
 warpAffine(Img, rotateImg, matrix, Size(length, length), 1, 0, Scalar(255, 255, 255));//原大小进行仿射变换
}

//通过霍夫变换计算角度
double CalcDegree(const Mat& srcImage)
{
 Mat midImage;
 Sobel(srcImage, midImage, -1, 0, 1, 5);
 //通过霍夫变换检测直线
 vector<Vec2f> lines;
 HoughLines(midImage, lines, 1, CV_PI / 180, 300, 0, 0);//阈值越大,精度越高
 //根据阈值由大到小设置了三个阈值,如果经过大量试验后,可以固定一个适合的阈值。
 if (!lines.size())
 {
     HoughLines(midImage, lines, 1, CV_PI / 180, 200, 0, 0);
 }
 if (!lines.size())
 {
     HoughLines(midImage, lines, 1, CV_PI / 180, 150, 0, 0);
 }
 float all_t = 0;
 for (size_t i = 0; i < lines.size(); i++)
 {
     float theta = lines[i][1];//选择角度最小的角作为旋转角
     //计算所有角度
     all_t += theta;
 }
 float average = all_t / lines.size(); //对所有角度求平均
 double degree = degreeTurn(average) - 90;
 return degree;
}


int main()
{
 // 存放所有路径名
 vector<string> m_item;
 //string m_pathname="D:\\Study\\temp\\image\\*.jpg";
 string m_pathname = "image\\*.jpg";
 glob(m_pathname, m_item);
 /*
 路径测试
 vector<string>::iterator it;
 for (it=m_item.begin();it!= m_item.end() ; it++)
 {
     cout << *it << endl;
 }*/


 // 处理每一个图片
 for (int i = 0; i < m_item.size(); ++i)
 {

     Mat src = imread(m_item[i]);
     if (src.empty())
     {
         cout << "加载图片 :" << m_item[i] << " 失败!" << endl;
         continue;
     }
     Mat gray_dst, result_dst;
     cvtColor(src, gray_dst, COLOR_BGR2GRAY);
     // 去噪处理
     MediaFilter(gray_dst, result_dst);

     /*
         去噪处理后 图片显示测试代码
     */
     namedWindow("原图", WINDOW_NORMAL);
     imshow("原图", src);

     namedWindow("灰度图", WINDOW_NORMAL);
     imshow("灰度图", gray_dst);
     // 去噪处理
     MediaFilter(gray_dst, result_dst);

     namedWindow("中值滤波去噪后", WINDOW_NORMAL);
     imshow("中值滤波去噪后", result_dst);

     //cout << "处理图片 :" << m_item[i] << " 成功!" << endl;

     // 灰度直方图
     //int nRows = 600, nCols = 800;
     //Mat g_dstImg(nRows, nCols, CV_8UC1, Scalar::all(0)); // 新建画布
     //namedWindow("g_dstImg", WINDOW_AUTOSIZE);
     //imshow("g_dstImg", g_dstImg);


     
     //Mat histImg = equalize_hist(result_dst);
     
     // namedWindow("均值化图", WINDOW_NORMAL);
     //imshow("均值化图", histImg);

     // drawHist(result_dst);
     drawHist(result_dst);
     // adaptiveThreshold(result_dst, temp, 255,ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY,21,10);
     //namedWindow("原图", WINDOW_NORMAL);
     //imshow("原图", histImg);

     Mat *decect=new Mat(result_dst);
     int dec=DetectThreshold(decect);
     
     cout << dec << endl;
     Mat binaryImg;
     threshold(result_dst, binaryImg, dec, 255, CV_THRESH_BINARY);
     namedWindow("二值图", WINDOW_NORMAL);
     imshow("二值图", binaryImg);


     //Mat angleImg;
     //angleCount(result_dst,angleImg);
     //namedWindow("角度图", WINDOW_NORMAL);
     //imshow("角度图", angleImg);



     // 输出二值图片

     //string strnn;
     //strnn += ".\\new\\";
     //strnn += m_item[i];
     //strnn += +".jpg";
     //cout << strnn << endl;
     //imwrite(strnn, binaryImg);




     waitKey(0);
 }


 waitKey(0);
 return 0;
}

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
OpenCV中矩阵的归一化
原帖地址:http://windrocblog.sinaapp.com/?p=486       图像处理中,图片像素点单通道值一般是[0-255]的unsigned char类型,将其转化到[0,1]之间,更方便计算,这就需要用到矩阵的归一化运算。
623 0
OPENCV显示图像
#include "cv.h"#include "highgui.h"#include "math.h" int main(){    IplImage* pimg;  //声明指针    //载入图像    pimg = cvLoadImage("D:\\baboon.
650 0
opencv透视变换
opencv透视变换 实现透视变换 目标: 在这篇教程中你将学到: 1、如何进行透视变化 2、如何生存透视变换矩阵 理论: 什么是透视变换: 1、透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。
1442 0
OpenCV 判断点是否在多边形内
OpenCV 判断点是否在多边形内 目的 在这个教程中我们将学习如何使用 OpenCV 函数 pointPolygonTest 代码 详细代码如下 #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #inc
6327 0
OPenCV 轮廓发现
OPenCV 轮廓发现
17 0
无人车行人识别---opencv
无人车行人识别---opencv
33 0
【OpenCV学习】抠图
作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ #include "cv.h" #include "highgui.h" #include CvPoint prev_pt={-1,-1} ; CvPoint pt_beg={-1,-...
604 0
+关注
流楚丶格念
csdn平台优质创作者,51cto TOP博主,360图书馆科技博主,燕山大学目前大三在读,日拱一卒,功不唐捐,加油!!!
1010
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载