Introdução
Em desenvolvimento…
Código no OpenCV
O código implementado pode ser visto a seguir:
Listagem 1. pontilhismo.cpp
#include <iostream>
#include <opencv2/opencv.hpp>
#include <fstream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <numeric>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace cv;
#define STEP 4
#define JITTER 5
#define RAIO 6
#define RAIOCANNY 9
#define CANNY 40
int main(int argc, char** argv){
vector<int> yrange;
vector<int> xrange;
Mat image, frame, points, border;
int width, height, gray;
int x, y;
image= imread(argv[1],CV_LOAD_IMAGE_GRAYSCALE);
srand(time(0));
if(!image.data){
cout << "nao abriu" << argv[1] << endl;
cout << argv[0] << " imagem.jpg";
exit(0);
}
Canny(image, border,CANNY,3*CANNY);
imshow("canny", border);
waitKey(0);
width=image.size().width;
height=image.size().height;
xrange.resize(height/STEP);
yrange.resize(width/STEP);
iota(xrange.begin(), xrange.end(), 0);
iota(yrange.begin(), yrange.end(), 0);
for(uint i=0; i<xrange.size(); i++){
xrange[i]= xrange[i]*STEP+STEP/2;
}
for(uint i=0; i<yrange.size(); i++){
yrange[i]= yrange[i]*STEP+STEP/2;
}
points = Mat(height, width, CV_8U, Scalar(255));
random_shuffle(xrange.begin(), xrange.end());
for(auto i : xrange){
random_shuffle(yrange.begin(), yrange.end());
for(auto j : yrange){
x = i+rand()%(2*JITTER)-JITTER+1;
y = j+rand()%(2*JITTER)-JITTER+1;
if(border.at<uchar>(i,j)==255){
x = i;
y = j;
gray = image.at<uchar>(x,y);
circle(points, cv::Point(y,x), RAIOCANNY, gray, -1, CV_AA);
}
else{
gray = image.at<uchar>(x,y);
circle(points, cv::Point(y,x), RAIO, gray, -1, CV_AA);
}
}
}
imshow("result", points);
waitKey(0);
imwrite("pontos.jpg", points);
return 0;
}
Resultados
Podemos ver o resultado da aplicação do filtro a seguir:

Figura 1. Imagem de entrada

Figura 2. Imagem de saída.