AnswerOpenCV一周佳作欣赏(0615-0622)

一、How to make auto-adjustments(brightness and contrast) for image Android Opencv Image Correction

i'm using OpenCV for Android.
I would like to know,how to make image correction(auto adjustments of brightness/contrast) for image(bitmap) in android via OpenCV or that can be done by native ColorMatrixFilter from Android!??

I tried to google,but didn't found good tutorials/examples.
So how can i achieve my goal? Any ideas?
Thanks!


算法问题,需要寻找到自动调整亮度和对比度的算法。

回答:

Brightness and contrast is linear operator with parameter alpha and beta

O(x,y) = alpha * I(x,y) + beta

In OpenCV you can do this with convertTo.

The question here is how to calculate alpha and beta automatically ?

Looking at histogram, alpha operates as color range amplifier, beta operates as range shift.

Automatic brightness and contrast optimization calculates alpha and beta so that the output range is 0..255.

input range = max(I) - min(I)
 
wanted output range = 255;
 
alpha = output range / input range = 255 / ( max(I) - min(I) )

min(O) = alpha * min(I) beta
beta = -min(I) * alpha

Histogram Wings Cut (clipping)

To maximize the result of it's useful to cut out some color with few pixels.

This is done cutting left right and wings of histogram where color frequency is less than a value (typically 1%). Calculating cumulative distribution from the histogram you can easly find where to cut.

may be sample chart helps to understand:

image description


By the way BrightnessAndContrastAuto could be named normalizeHist because it works on BGR and gray images stretching the histogram to the full range without touching bins balance. If input image has range 0..255 BrightnessAndContrastAuto will do nothing.

Histogram equalization and CLAE works only on gray images and they change grays level balancing. look at the images below:

Normalization vs Equalization

也就是实现了彩色的颜色增强算法
  void BrightnessAndContrastAuto(const cv::Mat &src, cv::Mat &dst, float clipHistPercent)
  {
    CV_Assert(clipHistPercent >= 0);
    CV_Assert((src.type() == CV_8UC1) || (src.type() == CV_8UC3) || (src.type() == CV_8UC4));
    int histSize = 256;
    float alpha, beta;
    double minGray = 0, maxGray = 0;
    //to calculate grayscale histogram
    cv::Mat gray;
    if (src.type() == CV_8UC1) gray = src;
    else if (src.type() == CV_8UC3) cvtColor(src, gray, CV_BGR2GRAY);
    else if (src.type() == CV_8UC4) cvtColor(src, gray, CV_BGRA2GRAY);
    if (clipHistPercent == 0)
    {
        // keep full available range
        cv::minMaxLoc(gray, &minGray, &maxGray);
    }
    else
    {
        cv::Mat hist; //the grayscale histogram
        float range[] = { 0256 };
        const float* histRange = { range };
        bool uniform = true;
        bool accumulate = false;
        calcHist(&gray, 10, cv::Mat (), hist, 1&histSize, &histRange, uniform, accumulate);
        // calculate cumulative distribution from the histogram
        std::vector<float> accumulator(histSize);
        accumulator[0= hist.at<float>(0);
        for (int i = 1; i < histSize; i++)
        {
            accumulator[i] = accumulator[i - 1+ hist.at<float>(i);
        }
        // locate points that cuts at required value
        float max = accumulator.back();
        clipHistPercent *= (max / 100.0); //make percent as absolute
        clipHistPercent /= 2.0// left and right wings
        // locate left cut
        minGray = 0;
        while (accumulator[minGray] < clipHistPercent)
            minGray++;
        // locate right cut
        maxGray = histSize - 1;
        while (accumulator[maxGray] >= (max - clipHistPercent))
            maxGray--;
    }
    // current range
    float inputRange = maxGray - minGray;
    alpha = (histSize - 1/ inputRange;   // alpha expands current range to histsize range
    beta = -minGray * alpha;             // beta shifts current range so that minGray will go to 0
    // Apply brightness and contrast normalization
    // convertTo operates with saurate_cast
    src.convertTo(dst, -1, alpha, beta);
    // restore alpha channel from source 
    if (dst.type() == CV_8UC4)
    {
        int from_to[] = { 33};
        cv::mixChannels(&src, 4&dst,1, from_to, 1);
    }
    return;
}
508489-20180622220655187-93343267.jpg
508489-20180622220656444-912778341.jpg

 效果比较不错。

二、Template matching behavior - Color

I am evaluating template matching algorithm to differentiate similar and dissimilar objects. What I found is confusing, I had an impression of template matching is a method which compares raw pixel intensity values. Hence when the pixel value varies I expected Template Matching to give a less match percentage.

I have a template and search image having same shape and size differing only in color(Images attached). When I did template matching surprisingly I am getting match percentage greater than 90%.

img = cv2.imread('./images/searchtest.png', cv2.IMREAD_COLOR)template = cv2.imread('./images/template.png', cv2.IMREAD_COLOR)
 
res = cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED)
 
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)print(max_val)

Template Image :
Template Image

Search Image :
Search Image

Can someone give me an insight why it is happening so? I have even tried this in HSV color space, Full BGR image, Full HSV image, Individual channels of B,G,R and Individual channels of H,S,V. In all the cases I am getting a good percentage.

Any help could be really appreciated.

image description


 
这个问题的核心就是彩色模板匹配。很有趣的问题。回答直接给出了source code,
https://github.com/LaurentBerger/ColorMatchTemplate
关于这个问题,我认为,彩色模板匹配的意义不是很大,毕竟用于定位的时候,黑白效果更好。
三、likely position of Feature Matching.

I am using Brute Force Matcher with L2 norm. Referring this link https://docs.opencv.org/2.4/doc/tutor...

After the process, I get below image as output

image description

What is the likely position of the object suggested by the feature matching?

I don't understand how to choose the likely position using this image :(

这是一个只知其一不知其二的问题,他能够找到旋转的地方,但是对于下一步如何做没有思路。其实,解决此类问题,最好的方法就是参考教程做一遍。

当然,管理员的回答非常明确:

to retrieve the position of your matched object, you need some further steps :

  • filter the matches for outliers
  • extract the 2d point locations from the keypoints
  • apply findHomography() on the matched 2d points to get a transformation matrix between your query and the scene image
  • apply perspectiveTransform on the boundingbox of the query object, to see, where it is located in the scene image.

我也给出具体回答:

image description

 //used surf
    //
    #include "stdafx.h"
    #include <iostream>
    #include "opencv2/core/core.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/features2d/features2d.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/nonfree/features2d.hpp"
    #include "opencv2/calib3d/calib3d.hpp"
    using namespace std;
    using namespace cv;
    int main( int argc, char** argv )
    {
        
        Mat img_1 ;
        Mat img_2 ;
        Mat img_raw_1 = imread("c1.bmp");
        Mat img_raw_2 = imread("c3.bmp");
        cvtColor(img_raw_1,img_1,CV_BGR2GRAY);
        cvtColor(img_raw_2,img_2,CV_BGR2GRAY);
        //-- Step 1: 使用SURF识别出特征点
        int minHessian = 400;
        SurfFeatureDetector detector( minHessian );
        std::vector<KeyPoint> keypoints_1, keypoints_2;
        detector.detect( img_1, keypoints_1 );
        detector.detect( img_2, keypoints_2 );
        //-- Step 2: 描述SURF特征
        SurfDescriptorExtractor extractor;
        Mat descriptors_1, descriptors_2;
        extractor.compute( img_1, keypoints_1, descriptors_1 );
        extractor.compute( img_2, keypoints_2, descriptors_2 );
        //-- Step 3: 匹配
        FlannBasedMatcher matcher;//BFMatcher为强制匹配
        std::vector< DMatch > matches;
        matcher.match( descriptors_1, descriptors_2, matches );
        //取最大最小距离
        double max_dist = 0; double min_dist = 100;
        for( int i = 0; i < descriptors_1.rows; i++ )
        { 
            double dist = matches[i].distance;
            if( dist < min_dist ) min_dist = dist;
            if( dist > max_dist ) max_dist = dist;
        }
        std::vector< DMatch > good_matches;
        for( int i = 0; i < descriptors_1.rows; i++ )
        { 
            if( matches[i].distance <= 3*min_dist )//这里的阈值选择了3倍的min_dist
            { 
                good_matches.push_back( matches[i]); 
            }
        }
        //-- Localize the object from img_1 in img_2
        std::vector<Point2f> obj;
        std::vector<Point2f> scene;
        for( int i = 0; i < (int)good_matches.size(); i++ )
        {    
            //这里采用“帧向拼接图像中添加的方法”,因此左边的是scene,右边的是obj
            scene.push_back( keypoints_1[ good_matches[i].queryIdx ].pt );
            obj.push_back( keypoints_2[ good_matches[i].trainIdx ].pt );
        }
        //直接调用ransac,计算单应矩阵
        Mat H = findHomography( obj, scene, CV_RANSAC );
        //图像对准
        Mat result;
        warpPerspective(img_raw_2,result,H,Size(2*img_2.cols,img_2.rows));
        Mat half(result,cv::Rect(0,0,img_2.cols,img_2.rows));
        img_raw_1.copyTo(half);
        imshow("result",result);
        waitKey(0);
        return 0;
    }
四、Run OpenCV to MFC
 I have reproduced this sample, in a MFC app.

The cv::Mat is a CDOcument variable member:

// Attributes
public:
std::vector<CBlob> m_blobs;
cv::Mat m_Mat;

and I draw rectangles over image, with an method (called at some time intervals, according FPS rate):

DrawBlobInfoOnImage(m_blobs, m_Mat);

Here is the code of this method:

void CMyDoc::DrawBlobInfoOnImage(std::vector<CBlob>& blobs, cv::Mat& Mat)
{
for (unsigned int i = 0;i < blobs.size();++i)
{
    if (blobs[i].m_bStillBeingTracked)
    {
        cv::rectangle(Mat, blobs[i].m_rectCurrentBounding, SCALAR_RED, 2);
        double dFontScale = blobs[i].m_dCurrentDiagonalSize / 60.0;
        int nFontThickness = (int)roundf(dFontScale * 1.0);
        cv::putText(Mat, (LPCTSTR)IntToString(i), blobs[i].m_vecPointCenterPositions.back(), CV_FONT_HERSHEY_SIMPLEX, dFontScale, SCALAR_GREEN, nFontThickness);
    }
}
}

but the result of this method is something like that:

image description

My question is: how can I draw only the last blobs result over my image ?

I have tried to clean up m_Mat, and to enable to draw only blobs.size() - 1 blob over image, none of this worked ...


非常有意思的问题,主要就是说他能够用mfc调用oepncv了,但是不知道如何将视频中的框子正确显示(也就是不要有拖尾)

这个也是对问题思考不是很深造成的问题。其实,解决的方法无外乎两个

一是直接修改视频流,也就是在原来的“读取-显示”循环里面添加一些东西(也就是框子),如果是这种方法,你使用或者不使用mfc基本没有什么影响;

比如<PariticalFilter在MFC上的运行,源代码公开>

https://www.cnblogs.com/jsxyhelu/p/6336429.html

二是采用mfc的机制。mfc不是都是对话框吗?那就创建一个窗体,专门用来显示这个矩形就好啦。 

比如<GreenOpenPaint的实现(五)矩形框>https://www.cnblogs.com/jsxyhelu/p/6354341.html

 

五、How to find the thickness of the red color sealent in the image ????

Hi,

I want to find the thickness of the red colored sealent in the image.

First I'm extracting the sealent portion by using findcontours by having minimum and maximum conotur area.And then check the Area,length and thickness of the sealent,i can find the area as well as length but i m not able to find the thickness of the sealent portion.

Please help me guys........below is the example image.

http://answers.opencv.org/upfiles/15295661161373758.jpg


提示一下:

do a distance transform and a skeleton on the binary image.

这是一个算法问题,具体解决,下周给出实现。大家可以先研究一下。

 


来自为知笔记(Wiz)


转载于:https://www.cnblogs.com/jsxyhelu/p/9215646.html

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

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

相关文章

所有其他指标均无用

对于队列&#xff0c;无论是实现为JMS &#xff0c;数据库表&#xff08;即Ruby的Delayed :: Job用于队列的什么&#xff09;&#xff0c;甚至是Amazon的SQS &#xff0c;用于评估队列状态的最常见指标是其长度。 从本质上讲&#xff0c;可以基于在任何给定时间队列中驻留多少消…

类似苹果数据线的android,除了常见的安卓、苹果、Type-c,还有哪些你不知道的手机数据线?...

随着智能手机日益发展&#xff0c;辅助智能手机的数据线配件也越来越多样。现在我们最常见的无非就是标准Micro usb口、正反随便插的Type-c接口、还有苹果Lightning数据线&#xff0c;那么除了这些类型数据线&#xff0c;你知道如今市面上还有哪些更方便好用的手机数据线吗&…

canvas入门实战--邀请卡生成与下载

1.前言 写了很多的javascript和css3的文章&#xff0c;是时候写一篇canvas的了。canvas是html5提供的一个新的功能&#xff01;至于作用&#xff0c;就是一个画布。然后画笔就是javascript。canvas的用途非常的广&#xff0c;特别是html5游戏以及数据可视化这两个方面。现在can…

Apache ActiveMQ 5.9发布

Apache ActiveMQ团队刚刚发布了新的ActiveMQ 5.9版本 。 Apache ActiveMQ 5.9发布 自从先前的5.8版本以来&#xff0c;此版本是8个月的辛苦工作。 在此发行版中&#xff0c;我们将像往常一样对代理进行增强&#xff0c;并使用最新的协议&#xff08;例如AMQP和MQTT&#xff…

android 美颜录像,Android 关于美颜/滤镜 利用PBO从OpenGL录制视频

前言上次我写了一遍文章《Android 关于美颜/滤镜 从OpenGl录制视频的一种方案》&#xff0c;里面利用ImageReader来从获取Surface上获取数据&#xff0c;但是经过熊皮皮的提醒&#xff0c;我发现多PBO的确可以实现跟ImageReader一样的效果&#xff0c;并且版本要求仅为Android4…

Java对象到对象映射器

我在该项目上使用了Dozer一段时间。 但是&#xff0c;最近我遇到了一个非常有趣的错误&#xff0c;它促使我环顾四周&#xff0c;并尝试使用其他“对象到对象”映射器。 这是我找到的工具列表&#xff1a; 推土机&#xff1a;推土机是Java Bean到Java Bean的映射器&#xff…

android媒体播放框架,Android 使用超简单的多媒体播放器JiaoZiVideoPlayer

在之前的项目中用到了视频播放的功能&#xff0c;在网上看了看使用了大家用的比较多的一个开源项目JiaoZiVideo可以迅速的实现视频播放的相关功能。JiaoZiVideo的简单使用集成了JiaoZiVideo后仅需这几行代码就可以实现播放视频JZVideoPlayerStandard jzVideoPlayerStandard (J…

送福利:ROKID 语音开发板免费送,开启你的物联网之旅

都让一让&#xff0c;我说个事情&#xff1a;掘金联合 Rokid 开发者社区给大家发福利啦&#xff01; 掘金联合 Rokid 开发者社区为大家准备了一些福利&#xff0c;只要秀出你的 skill 和技术栈&#xff0c;就有可能获得 Rokid 全栈语音智能开发套件。 ? Rokid开箱试用活动 活…

如何使用JavaScript控制台改进工作流程

作为Web开发人员&#xff0c;很有必要了解如何调试代码。后台开发我们经常使用外部库来记录日志&#xff0c;并在某些情况下格式化显示日志&#xff0c;前端我们会使用断点和控制台&#xff0c;但是我们浏览器的控制台比我们想象的要强大得多。 当我们考虑控制台时&#xff0c…

select、poll、epoll之间的区别总结[整理]

原文:https://www.cnblogs.com/Anker/p/3265058.html 好文章收藏下&#xff0c;慢慢品味 select&#xff0c;poll&#xff0c;epoll都是IO多路复用的机制。I/O多路复用就通过一种机制&#xff0c;可以监视多个描述符&#xff0c;一旦某个描述符就绪&#xff08;一般是读就绪或者…

JPA(七):映射关联关系------映射双向多对一的关联关系

映射双向多对一的关联关系 修改Customer.java package com.dx.jpa.singlemanytoone;import java.util.Date; import java.util.HashSet; import java.util.Set;import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; impo…

如何优雅的绘制一棵省市区三级可选择的树?

开始 总结一下 开发过程中的思路想法 各位大佬们看看就好 首先你拥有的数据结构 所有省市区的信息列表 以及已经选中的信息 用的是element-ui的 el-tree const cityStorage {provinceList:[{id: 1, provinceId: "110000", name: "北京市"}],//所有省ci…

html click事件 参数,vue 实现click同时传入事件对象和自定义参数

这篇文章主要介绍了vue 实现click同时传入事件对象和自定义参数&#xff0c;具有很好的参考价值&#xff0c;希望对大家有所帮助。一起跟随小编过来看看吧仅仅传入自定义参数HTMLdddddJS代码new Vue({el:#app,methods:{tm:function(e){console.log(e);}}})仅仅传入事件对象HTML…

Android学习(七)—— Android布局

Android布局 1、LinearLayout 线性布局&#xff0c;这种布局在平时的开发中用的最多&#xff0c;内部控件只能水平或竖直进行排列&#xff0c;在搭建较复杂的界面时会有点麻烦。 常用属性 android:orientation 控制控件排列方向&#xff0c;属性值为垂直&#xff08;vertical…

不一样的ZTree,权限树.js插件

每一个有趣的创新&#xff0c;都源于苦逼的生活。在最近的工作中&#xff0c;遇到一个做权限管理筛选的需求。 简单总结需求&#xff1a; 1展示一个组织中的组织结构 2通过点击组织结构中的任意一个节点可以向上向下查询对应的组织结构 如果你不想苦逼的重复劳动&#xff0c;还…

JavaFX 2:如何加载图像

这是有关如何在JavaFX 2应用程序中加载图像的JavaFX教程。 使用ImageView可以轻松完成此操作。 ImageView是一个节点&#xff0c;用于绘制加载有Image类的图像。 因此&#xff0c;您将首先使用Image类加载图像&#xff0c;然后使用ImageView显示它。 我还将在这里演示如何从本地…

记HTML5 a 标签的一个小坑

今天写了段简单的代码&#xff0c;点击<a>标签时却抛出了这个错误&#xff1a;Uncaught TypeError: download is not a function。代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><…

C#线程 ---- 线程同步详解

线程同步 说明&#xff1a;接上一篇&#xff0c;注意分享线程同步的必要性和线程同步的方法。 测试代码下载&#xff1a;https://github.com/EkeSu/C-Thread-synchronization-C-.git 一、什么是线程同步&#xff1a; 在同一时间只允许一个线程访问资源的情况称为线程同步。 二、…

响应式方案调研及前端开发管理思考

网易首页响应式风格实现技术调研网易首页实现页面&#xff08;字体&#xff09;响应式风格的方式是在不同尺寸的视口中使用不同的容器类&#xff0c;如图 1所示。当视口大于等于1420px时&#xff0c;使用大尺寸容器类 &#xff08;index2017_1200_wrap&#xff0c;width: 1200p…

linux nexus启动_Linux一键部署Nexus 3私服仓库自动化部署脚本

此脚本是Linux一键部署Nexus 3私服仓库自动化脚本&#xff0c;有需要朋友可以参考&#xff0c;脚本内容如下&#xff1a;环境准备&#xff1a;操作系统&#xff1a;CentOS Linux release 7.8.2003软件版本&#xff1a;Docker&#xff1a;docker-ce-19.03.12[rootlocalhost ~]# …